Private/Invoke-EvergreenWebRequest.ps1

function Invoke-EvergreenWebRequest {
    <#
        .SYNOPSIS
            Validates and return responses from Invoke-WebRequest
            Enables normalisation for all public functions and across PowerShell/Windows PowerShell
            Some validation of $Uri is expected before passing to this function
        .DESCRIPTION
            With -Raw, the response is written to a temporary file to avoid response parsing, then returned as UTF-8 text.
            Binary responses are not supported by -Raw.
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [System.String] $Uri,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String] $ContentType,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.Collections.Hashtable] $Headers,

        [Parameter()]
        [ValidateSet("Default", "Get", "Head", "Post")]
        [System.String] $Method = "Default",

        [Parameter()]
        [ValidateSet("Default", "Tls", "Tls11", "Tls12", "Tls13")]
        [System.String] $SslProtocol = "Tls12",

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [System.String] $UserAgent = (Get-EvergreenUserAgent),

        [Parameter()]
        [System.Management.Automation.SwitchParameter] $Raw,

        [Parameter()]
        [System.Management.Automation.SwitchParameter] $SkipCertificateCheck,

        [Parameter()]
        [ValidateSet("Content", "RawContent", "Headers", "All")]
        [System.String] $ReturnObject = "Content"
    )

    # Disable the Invoke-WebRequest progress bar for faster downloads
    if ($PSBoundParameters.ContainsKey("Verbose")) {
        $ProgressPreference = [System.Management.Automation.ActionPreference]::Continue
    }
    else {
        $ProgressPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
    }

    $SkipCertificateCheckEnabled = ($script:SkipCertificateCheck -eq $true -or $SkipCertificateCheck.IsPresent)
    $IsPSCore = Test-PSCore
    $TempFile = $null
    $PreviousCertificatePolicy = $null
    $RestoreCertificatePolicy = $false
    $PreviousSecurityProtocol = $null
    $RestoreSecurityProtocol = $false

    try {
        if ($PSCmdlet.ShouldProcess($Uri, "Invoke-WebRequest")) {
            # Windows PowerShell 5.1 does not support SkipCertificateCheck on Invoke-WebRequest.
            # Its ServicePointManager fallback is process-wide, so restore the previous policy below.
            if ($SkipCertificateCheckEnabled -and -not $IsPSCore) {
                if (-not ("TrustAllCertsPolicy" -as [type])) {
                    Add-Type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
        return true;
    }
}
"@

                }
                $PreviousCertificatePolicy = [System.Net.ServicePointManager]::CertificatePolicy
                [System.Net.ServicePointManager]::CertificatePolicy = New-Object -TypeName "TrustAllCertsPolicy"
                $RestoreCertificatePolicy = $true
                Write-Verbose -Message "$($MyInvocation.MyCommand): Trusting certificates for this request."
            }

            if (-not $IsPSCore) {
                $PreviousSecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol
                $RestoreSecurityProtocol = $true
                if ($SslProtocol -eq "Tls13") {
                    throw [System.NotSupportedException]::New("TLS 1.3 is not supported by Windows PowerShell 5.1.")
                }
                $RequestedProtocol = if ($PSBoundParameters.ContainsKey("SslProtocol") -and $SslProtocol -ne "Default") {
                    [System.Enum]::Parse([System.Net.SecurityProtocolType], $SslProtocol, $true)
                }
                else {
                    [System.Net.SecurityProtocolType]::Tls12
                }
                [System.Net.ServicePointManager]::SecurityProtocol = $PreviousSecurityProtocol -bor $RequestedProtocol
            }

            # Build the Invoke-WebRequest parameters
            $params = @{
                Uri             = $Uri
                Method          = $Method
                UserAgent       = $UserAgent
                UseBasicParsing = $true
            }

            # Set additional parameters
            if ($PSBoundParameters.ContainsKey("ContentType")) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Adding ContentType."
                $params.ContentType = $ContentType
            }
            if ($PSBoundParameters.ContainsKey("Headers")) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Adding Headers."
                $params.Headers = $Headers
            }
            if ($SkipCertificateCheckEnabled -and $IsPSCore) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Adding SkipCertificateCheck."
                $params.SkipCertificateCheck = $true
            }
            if ($PSBoundParameters.ContainsKey("SslProtocol") -and $IsPSCore) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Adding SslProtocol."
                $params.SslProtocol = $SslProtocol
            }
            if ($PSBoundParameters.ContainsKey("Raw")) {
                $TempFile = New-TemporaryFile
                $params.OutFile = $TempFile.FullName
                $params.PassThru = $true
                Write-Verbose -Message "$($MyInvocation.MyCommand): Using temporary response file."
            }
            if (Test-ProxyEnv) {
                $params.Proxy = $script:EvergreenProxy
            }
            if (Test-ProxyEnv -Creds) {
                $params.ProxyCredential = $script:EvergreenProxyCreds
            }
            #endregion

            # Output the parameters when using -Verbose
            foreach ($item in $params.GetEnumerator()) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Invoke-WebRequest parameter: $($item.name): $($item.value)."
            }

            # Raw response files are returned as UTF-8 text for existing text-response callers.
            if ($PSBoundParameters.ContainsKey("Raw")) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Raw output is UTF-8 text; binary responses are not supported."
            }
            $Response = Invoke-WebRequest @params

            if ($null -ne $Response) {
                Write-Verbose -Message "$($MyInvocation.MyCommand): Response: $($Response.StatusCode)."
                Write-Verbose -Message "$($MyInvocation.MyCommand): Content type: $($Response.Headers.'Content-Type')."

                # Output content from the response
                switch ($ReturnObject) {
                    "All" {
                        Write-Verbose -Message "$($MyInvocation.MyCommand): Returning entire response."
                        Write-Output -InputObject $Response
                    }
                    "Headers" {
                        Write-Verbose -Message "$($MyInvocation.MyCommand): Returning headers."
                        Write-Output -InputObject $Response.Headers
                    }
                    "RawContent" {
                        Write-Verbose -Message "$($MyInvocation.MyCommand): Returning raw content of length: $($Response.RawContent.Length)."
                        Write-Output -InputObject $Response.RawContent
                    }
                    default {
                        if ($PSBoundParameters.ContainsKey("Raw")) {
                            $Content = Get-Content -LiteralPath $TempFile.FullName -Raw -Encoding UTF8
                        }
                        else {
                            $Content = $Response.Content
                        }
                        Write-Verbose -Message "$($MyInvocation.MyCommand): Returning content of length: $($Content.Length)."
                        Write-Output -InputObject $Content
                    }
                }
            }
        }
    }
    catch {
        Write-Warning -Message "$($MyInvocation.MyCommand): $($_.Exception.Message), with: $Uri."
        Write-Warning -Message "$($MyInvocation.MyCommand): For troubleshooting steps see: $($script:resourceStrings.Uri.Info)."
        throw
    }
    finally {
        if ($RestoreCertificatePolicy) {
            [System.Net.ServicePointManager]::CertificatePolicy = $PreviousCertificatePolicy
        }
        if ($RestoreSecurityProtocol) {
            [System.Net.ServicePointManager]::SecurityProtocol = $PreviousSecurityProtocol
        }
        if ($null -ne $TempFile -and (Test-Path -LiteralPath $TempFile.FullName)) {
            Remove-Item -LiteralPath $TempFile.FullName -Force -ErrorAction Stop
        }
    }
}