Private/PVEApiClient.ps1

#
# Proxmox VE
# Generated module to access all Proxmox VE Api Endpoints
# Version: 0.3
# Contact: amna.wolf@gmail.com
# Generated by OpenAPI Generator: https://openapi-generator.tech
#

function Invoke-PVEApiClient {
    [OutputType('System.Collections.Hashtable')]
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory)]
        [string]$Uri,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$Accepts,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$ContentTypes,
        [Parameter(Mandatory)]
        [hashtable]$HeaderParameters,
        [Parameter(Mandatory)]
        [hashtable]$FormParameters,
        [Parameter(Mandatory)]
        [hashtable]$QueryParameters,
        [Parameter(Mandatory)]
        [hashtable]$CookieParameters,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Body,
        [Parameter(Mandatory)]
        [string]$Method,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$ReturnType,
        [Parameter(Mandatory)]
        [bool]$IsBodyNullable
    )

    'Calling method: Invoke-PVEApiClient' | Write-Debug
    $PSBoundParameters | Out-DebugParameter | Write-Debug

    $Configuration = Get-PVEConfiguration
    $RequestUri = $Configuration["BaseUrl"] + $Uri
    $SkipCertificateCheck = $Configuration["SkipCertificateCheck"]

    # accept, content-type headers
    $Accept = SelectHeaders -Headers $Accepts
    if ($Accept) {
        $HeaderParameters['Accept'] = $Accept
    }

    $ContentType= SelectHeaders -Headers $ContentTypes
    if ($ContentType) {
        $HeaderParameters['Content-Type'] = $ContentType
    }

    # add default headers if any
    foreach ($header in $Configuration["DefaultHeaders"].GetEnumerator()) {
        $HeaderParameters[$header.Name] = $header.Value
    }

    # exit if not logged in
    if(!$Script:AuthData["LoggedIn"]){
        throw "Not connected, please use Invoke-PVELogin first."
    }

    # adding PVE auth headers
    switch($Script:Configuration["LoginMethod"]){
        { $_ -eq "token" } {
            $HeaderParameters["Authorization"] = DecryptSecureString -SecureString $Script:AuthData["PVEAPIToken"]
        }
        { $_ -eq "ticket"} {
            $HeaderParameters["Cookie"] = "PVEAuthCookie=$(DecryptSecureString -SecureString $Script:AuthData["Ticket"])"
            if($Method -match "(post|put|delete)"){
                $HeaderParameters["CSRFPreventionToken"] = DecryptSecureString -SecureString $Script:AuthData["CSRFPreventionToken"]
            }
        }
    }
    
    # construct URL query string
    $HttpValues = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
    foreach ($Parameter in $QueryParameters.GetEnumerator()) {
        if ($Parameter.Value.Count -gt 1) { // array
            foreach ($Value in $Parameter.Value) {
                $HttpValues.Add($Parameter.Key + '[]', $Value)
            }
        } else {
            $HttpValues.Add($Parameter.Key,$Parameter.Value)
        }
    }
    # Build the request and load it with the query string.
    $UriBuilder = [System.UriBuilder]($RequestUri)
    $UriBuilder.Query = $HttpValues.ToString()

    # include form parameters in the request body
    if ($FormParameters -and $FormParameters.Count -gt 0) {
        $RequestBody = $FormParameters
    }

    if ($Body -or $IsBodyNullable) {
        $RequestBody = $Body
        if ([string]::IsNullOrEmpty($RequestBody) -and $IsBodyNullable -eq $true) {
            $RequestBody = "null"
        }
    }
    
    if($RequestBody -and $RequestBody -ne "null"){
        $RequestBody = ([System.Text.Encoding]::UTF8.GetBytes($RequestBody))
    }

    
    $RequestSplat = @{
        Uri             = $UriBuilder.Uri
        Method          = $Method
        Headers         = $HeaderParameters
        ErrorAction     = "Stop"
        UseBasicParsing = $true
        WebSession      = $Configuration["webSession"]
    }
    
    if($RequestBody -and $RequestBody -ne "null"){
        $RequestSplat["Body"] = $RequestBody
    }

    if ($SkipCertificateCheck -eq $true) {
        $RequestSplat.SkipCertificateCheck = $true
    }

    if ($Configuration["Proxy"] -ne $null) {
         $RequestSplat.Proxy = $Configuration["Proxy"].GetProxy($UriBuilder.Uri) 
         $RequestSplat.ProxyUseDefaultCredentials = $true
    }
    
    
    $Response = Invoke-WebRequest @RequestSplat
    return @{
        Response = DeserializeResponse -Response $Response -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
        StatusCode = $Response.StatusCode
        Headers = $Response.Headers
    }
}

# Select JSON MIME if present, otherwise choose the first one if available
function SelectHeaders {
    Param(
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [String[]]$Headers
    )

    foreach ($Header in $Headers) {
        if (IsJsonMIME -MIME $Header) {
            return $Header
        }
    }

    if (!($Headers) -or $Headers.Count -eq 0) {
        return $null
    } else {
        return $Headers[0] # return the first one
    }
}

function IsJsonMIME {
    Param(
        [Parameter(Mandatory)]
        [string]$MIME
    )

    if ($MIME -match "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$") {
        return $true
    } else {
        return $false
    }
}

function DeserializeResponse {
    Param(
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$ReturnType,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Response,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$ContentTypes
    )

    if ($ContentTypes -eq $null) {
        $ContentTypes = [string[]]@()
    }

    if ([string]::IsNullOrEmpty($ReturnType) -and $ContentTypes.Count -eq 0) { # void response
        return $Response
    } elseif ($ReturnType -match '\[\]$') { # array
        return (ConvertFrom-Json $Response).data
    } elseif (@("String", "Boolean", "System.DateTime") -contains $ReturnType) { # string, boolean ,datetime
        return (ConvertFrom-Json $Response).data
    } else { # others (e.g. model, file)
        if ($ContentTypes) {
            $ContentType = $null
            if ($ContentTypes.Count -gt 1) {
                $ContentType = SelectHeaders -Headers $ContentTypes
            } else {
                $ContentType = $ContentTypes[0]
            }

            if (IsJsonMIME -MIME $ContentType) { # JSON
                return (ConvertFrom-Json $Response).data
            } else { # XML, file, etc
                return $Response
            }
        } else { # no content type in response header, returning raw response
            return $Response
        }
    }
}