Private/Invoke-AzTableRestMethod.ps1
|
function Invoke-AzTableRestMethod { <# .SYNOPSIS Sends an authenticated HTTP request to the Azure Table Storage REST API. .DESCRIPTION Builds the full request URL (appending the SAS token when applicable), obtains the correct authorization headers, and dispatches the request. Returns a PSCustomObject with Content (parsed JSON) and Headers (response headers) so that callers can inspect continuation tokens. .OUTPUTS [PSCustomObject] with properties: - Content : Parsed JSON body, or $null for empty responses - Headers : Response header collection - StatusCode : HTTP status code (int) #> [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory)] [PSCustomObject]$Context, [Parameter(Mandatory)] [ValidateSet('GET', 'POST', 'PUT', 'DELETE', 'PATCH')] [string]$Method, # Path after the base endpoint, e.g. "Tables", "mytable()", "Tables('mytable')" [Parameter(Mandatory)] [string]$Resource, # Optional OData query string (without leading '?'), e.g. "$filter=PartitionKey eq 'pk'" [string]$QueryString = '', # Optional request body (will be serialized to JSON) [object]$Body = $null, # Optional ETag for conditional operations (If-Match header) [string]$ETag = $null ) $contentType = '' $bodyBytes = $null if ($null -ne $Body) { $contentType = 'application/json' $bodyJson = $Body | ConvertTo-Json -Depth 10 -Compress $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($bodyJson) } # Build authorization headers $authHeaders = Get-AzTableAuthorizationHeader ` -Context $Context ` -Method $Method ` -Resource $Resource ` -ContentType $contentType $requestHeaders = @{ 'DataServiceVersion' = '3.0;NetFx' 'MaxDataServiceVersion' = '3.0;NetFx' 'Accept' = 'application/json;odata=nometadata' } foreach ($key in $authHeaders.Keys) { $requestHeaders[$key] = $authHeaders[$key] } if ($ETag) { $requestHeaders['If-Match'] = $ETag } # Build URL - SAS token always goes first so OData params are appended afterward $url = "$($Context.Endpoint)/$Resource" if ($Context.AuthType -eq 'SasToken') { $url += $Context.SasToken # already starts with '?' if ($QueryString) { $url += "&$QueryString" } } elseif ($QueryString) { $url += "?$QueryString" } $requestParams = @{ Uri = $url Method = $Method Headers = $requestHeaders UseBasicParsing = $true ErrorAction = 'Stop' } if ($null -ne $bodyBytes) { $requestParams['Body'] = $bodyBytes $requestParams['ContentType'] = 'application/json' } try { $response = Invoke-WebRequest @requestParams $parsedContent = $null $rawContent = $response.Content if ($rawContent -is [byte[]]) { $rawContent = [System.Text.Encoding]::UTF8.GetString($rawContent) } if (-not [string]::IsNullOrWhiteSpace($rawContent)) { $parsedContent = $rawContent | ConvertFrom-Json } return [PSCustomObject]@{ Content = $parsedContent Headers = $response.Headers StatusCode = [int]$response.StatusCode } } catch { $statusCode = $null $errorMessage = $_.Exception.Message if ($_.Exception.Response) { $statusCode = [int]$_.Exception.Response.StatusCode } if ($_.ErrorDetails -and $_.ErrorDetails.Message) { $errorBody = $_.ErrorDetails.Message try { $errorObj = $errorBody | ConvertFrom-Json if ($errorObj.'odata.error'.message.value) { $errorMessage = $errorObj.'odata.error'.message.value } } catch { $errorMessage = $errorBody } } throw [System.Exception]::new( "Azure Table Storage request failed (HTTP $statusCode): $errorMessage", $_.Exception ) } } |