Pax8API/Private/Invoke-Pax8RestMethod.ps1

function Invoke-Pax8RestMethod {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [uri]$Uri,

        [Parameter(Mandatory)]
        [ValidateSet('GET', 'POST', 'PUT', 'PATCH', 'DELETE')]
        [string]$Method,

        [hashtable]$Headers,

        [object]$Body,

        [int]$MaximumRetryCount = 5,

        [int]$RetryIntervalSeconds = 2,

        [int]$TimeoutSec = 100,

        [switch]$Anonymous
    )

    $headersToSend = @{}
    if ($Headers) {
        foreach ($entry in $Headers.GetEnumerator()) {
            $headersToSend[$entry.Key] = $entry.Value
        }
    }

    if (-not $Anonymous -and $script:Pax8Session.AccessToken) {
        $headersToSend['Authorization'] = "Bearer $($script:Pax8Session.AccessToken)"
    }

    if (-not $headersToSend.ContainsKey('Accept')) {
        $headersToSend['Accept'] = 'application/json'
    }

    $jsonBody = $null
    if ($PSBoundParameters.ContainsKey('Body') -and $null -ne $Body) {
        if ($Body -is [string]) {
            $jsonBody = $Body
        } else {
            $jsonBody = $Body | ConvertTo-Json -Depth 80
        }
    }

    for ($attempt = 0; $attempt -le $MaximumRetryCount; $attempt++) {
        $responseHeaders = $null
        $statusCode = $null
        $invokeRestMethodCommand = Get-Command Invoke-RestMethod
        $request = @{
            Uri = $Uri
            Method = $Method
            Headers = $headersToSend
            ErrorAction = 'Stop'
            StatusCodeVariable = 'statusCode'
            ResponseHeadersVariable = 'responseHeaders'
            SkipHttpErrorCheck = $true
        }

        if ($invokeRestMethodCommand.Parameters.ContainsKey('TimeoutSec')) {
            $request['TimeoutSec'] = $TimeoutSec
        } else {
            if ($invokeRestMethodCommand.Parameters.ContainsKey('OperationTimeoutSeconds')) {
                $request['OperationTimeoutSeconds'] = $TimeoutSec
            }
            if ($invokeRestMethodCommand.Parameters.ContainsKey('ConnectionTimeoutSeconds')) {
                $request['ConnectionTimeoutSeconds'] = [Math]::Min(30, $TimeoutSec)
            }
        }

        if ($jsonBody) {
            $request['Body'] = $jsonBody
            $request['ContentType'] = 'application/json'
        }

        if ($Uri.Scheme -eq 'https' -and $invokeRestMethodCommand.Parameters.ContainsKey('HttpVersion')) {
            $request['HttpVersion'] = [version]'2.0'
        }

        try {
            $response = Invoke-RestMethod @request
        } catch {
            if ($attempt -ge $MaximumRetryCount) {
                throw
            }

            $delay = Get-Pax8RetryDelay -Headers $responseHeaders -Attempt ($attempt + 1) -DefaultSeconds $RetryIntervalSeconds
            Write-Verbose "Pax8 request failed before an HTTP response was returned. Retrying in $delay second(s)."
            Start-Sleep -Seconds $delay
            continue
        }

        if ($statusCode -in 429, 500, 502, 503, 504 -and $attempt -lt $MaximumRetryCount) {
            $delay = Get-Pax8RetryDelay -Headers $responseHeaders -Attempt ($attempt + 1) -DefaultSeconds $RetryIntervalSeconds
            Write-Verbose "Pax8 returned HTTP $statusCode. Retrying in $delay second(s)."
            Start-Sleep -Seconds $delay
            continue
        }

        if ($statusCode -ge 400) {
            $message = "Pax8 returned HTTP $statusCode for $Method $Uri."
            if ($response) {
                $detail = $response | ConvertTo-Json -Depth 20 -Compress
                $message = "$message Response: $detail"
            }

            throw [System.Net.Http.HttpRequestException]::new($message)
        }

        return $response
    }
}