Private/GetHttpRequestWithCookie.ps1

. "$PSScriptRoot/Constants.ps1";
. "$PSScriptRoot/Models/HttpException.ps1";

# Make a get request to a $url while forcing the instance using the ARRAfinity cookie with $instanceGuid
function GetHttpRequestWithCookie(
    [Parameter(Mandatory=$True)]
    [string]$defaultHostName,
    [Parameter(Mandatory=$True)]
    [string]$url,
    [Parameter(Mandatory=$True)]
    [System.TimeSpan]$requestTimeOut,
    [Parameter(Mandatory=$False)]
    [string]$instanceGuid,
    [Parameter(Mandatory=$False)]
    [Boolean]$logRequest = $True,
    [Parameter(Mandatory=$False)]
    [Boolean]$outputHtml = $False) {

    $timeOutSeconds = $requestTimeOut.TotalSeconds;
    if ($timeOutSeconds -lt 1) { throw "requestTimeOut requires to be at least 1 second or more." }

    $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession;
    $requestMessage = "Requesting $url";

    if (![string]::IsNullOrEmpty($instanceGuid)){
        $requestMessage = "$requestMessage for instance $instanceGuid";
        $cookie = New-Object System.Net.Cookie;

        # To force the instance you can set a cookie named ARRAffinity, this is what Azure uses to assign an Instance by ID
        # The domain name has to be the domain of the url calling the instance preceded with a '.'
        $cookie.Name = "ARRAffinity";
        $cookie.Value = $instanceGuid;
        $cookie.Domain = ".$defaultHostName";
        $session.Cookies.Add($cookie);
    }

    if ($logRequest){ Write-Host $requestMessage; }
    $timeOutSeconds = $requestTimeOut.TotalSeconds;

    try {
        $httpResponse = Invoke-WebRequest `
            -Uri $url `
            -WebSession $session `
            -TimeoutSec $timeOutSeconds `
            -ErrorAction SilentlyContinue `
            -WarningAction SilentlyContinue;
        return $httpResponse;
    }
    catch [Microsoft.PowerShell.Commands.HttpResponseException] {

        $webException = [HttpException]::new();

        $exception = $_.Exception;
        $message = $exception.Message;
        $statuseCode = $exception.Response.StatusCode;
        $statuseMessage = $exception.Response.ReasonPhrase;

        $webException.ResponseMessage = $statuseMessage;
        $webException.ResponseCode = $statuseCode;
        if($outputHtml) {
            $webException.ResponseData = $message;
        }

        throw $webException;
    }
    # Use custom exception object so it can be mocked
    catch {

        $webException = [HttpException]::new();
        $webException.Message = "$_".Trim();

        if ($_.Exception -eq $null) { throw $_; }

        # Regular statusCodes
        $statusCode = $_.Exception.Response.StatusCode;
        $responseMessage = $_.Exception.Response.StatusDescription;

        # Special case TimeOut
        if ($webException.Message -eq $Constants.InvokeWebRequestTimeOutMessage)
        {
            $statusCode = 408;
            $responseMessage = "Request Timeout";
        }

        if($outputHtml) {
            $sr = $null;
            try{
                # Attempt reading the body
                $reqstream = $_.Exception.Response.GetResponseStream();
                $reqstream.Seek(0, 0);
                $sr = [System.IO.StreamReader]::new($reqstream);
                $result = $sr.ReadToEnd();
                if([System.String]::IsNullOrEmpty($result) -eq $false){
                    $webException.ResponseData = $result.Trim();
                }

            } finally{
                if ($null -ne $sr -and $sr -is [System.IDisposable])
                {
                    $sr.dispose();
                }
            }
        }

        $webException.ResponseCode = if ($statusCode -eq $null) { -1 } else { $statusCode };
        
        # Other Exceptions
        if ([System.String]::IsNullOrEmpty($responseMessage) -eq $false) {
            $webException.ResponseMessage = $responseMessage;
            throw $webException;
        }

        $webException.ResponseMessage = $webException.Message.Trim();
        throw $webException;
    }
}