Private/Invoke-CloudApiRequest.ps1

function Invoke-CloudApiRequest {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Uri,
        
        [Parameter(Mandatory = $false)]
        [string]$Method = 'Get',
        
        [Parameter(Mandatory = $false)]
        [object]$Body = $null,
        
        [Parameter(Mandatory = $false)]
        [switch]$IsRetry
    )
    
    # Check if connected
    if (-not $script:CloudConnection -or -not $script:CloudConnection.Connected) {
        throw "Not connected to Cloud Server. Please run Connect-CloudServer first."
    }
    
    # Check if token is expired or about to expire (within 1 minute)
    if ($script:CloudConnection.TokenExpiresAt -and (Get-Date) -ge $script:CloudConnection.TokenExpiresAt.AddMinutes(-1)) {
        Write-Verbose "Token expired or expiring soon, re-authenticating..."
        
        try {
            # Reconstruct credential from stored secure data
            $savedCred = New-Object System.Management.Automation.PSCredential(
                $script:CloudConnection.CredentialUsername,
                $script:CloudConnection.CredentialSecurePassword
            )
            
            Connect-CloudServer -Server $script:CloudConnection.Server `
                                -Port $script:CloudConnection.Port `
                                -Credential $savedCred `
                                -IgnoreInvalidCertificate:$script:CloudConnection.IgnoreInvalidCertificate | Out-Null
            
            Write-Verbose "Re-authentication successful"
        }
        catch {
            throw "Failed to re-authenticate: $_"
        }
        finally {
            # Clear the temporary credential object
            if ($savedCred) {
                $savedCred = $null
            }
        }
    }
    
    # Build request parameters
    $requestParams = @{
        Uri = $Uri
        Method = $Method
        Headers = $script:CloudConnection.Headers
        WebSession = $script:CloudConnection.WebSession
    }
    
    if ($Body) {
        $requestParams['Body'] = ($Body | ConvertTo-Json -Depth 10)
    }
    
    # Add certificate bypass for PS6+
    if ($script:CloudConnection.IgnoreInvalidCertificate -and $PSVersionTable.PSVersion.Major -ge 6) {
        $requestParams['SkipCertificateCheck'] = $true
    }
    
    try {
        $response = Invoke-RestMethod @requestParams -UseBasicParsing
        return $response
    }
    catch {
        # Check if this is a 401 error and we haven't already retried
        if ($_.Exception.Response.StatusCode -eq 401 -and -not $IsRetry) {
            Write-Verbose "Received 401 error, attempting to re-authenticate..."
            
            try {
                # Reconstruct credential from stored secure data
                $savedCred = New-Object System.Management.Automation.PSCredential(
                    $script:CloudConnection.CredentialUsername,
                    $script:CloudConnection.CredentialSecurePassword
                )
                
                # Re-authenticate
                Connect-CloudServer -Server $script:CloudConnection.Server `
                                    -Port $script:CloudConnection.Port `
                                    -Credential $savedCred `
                                    -IgnoreInvalidCertificate:$script:CloudConnection.IgnoreInvalidCertificate | Out-Null
                
                Write-Verbose "Re-authentication successful, retrying request..."
                
                # Retry the request once with the new token
                return Invoke-CloudApiRequest -Uri $Uri -Method $Method -Body $Body -IsRetry
            }
            catch {
                throw "Failed to re-authenticate after 401 error: $_"
            }
            finally {
                # Clear the temporary credential object
                if ($savedCred) {
                    $savedCred = $null
                }
            }
        }
        else {
            # Either not a 401, or this is already a retry - just throw the error
            throw "API request failed: $_"
        }
    }
}

function get-softironlogo {

write-host " "
write-host " .:-=++ ++- ++. :- "
write-host " -+++++=-:::--==+++==-..:---:. "
write-host " .+++++++= +++++++++++= :++- "
write-host " ++++++++++==+++++++++++++++= "
write-host " =++++++++++++++++++++++++++++ "
write-host " =++++++++++++++- .++++++++ "
write-host " :+++++++++++++++- +++++++=. "
write-host " +++++++++++++-. "
write-host " ++++++=: -@ "
write-host " .++++. %@@% - "
write-host " :++. :%* #@@@@@@@ "
write-host " := %@@= -@@@@@@@ "
write-host " . :@@@@+ @@@@@ : "
write-host " %@@@@@# .@@@ =- "
write-host " :@@@@@@@@ @@= .++- "
write-host " -- -@@@- =+++: "
write-host " +@= =++++++. "
write-host " .=++++++++++= "
write-host " :::::-=- :+++++++++++++++- "
write-host " ++++++++ :+++++++++++++++ "
write-host " :-=++++++++++++++++++++++++++ "
write-host " =+++++++++++++++++++++++++++ "
write-host " =++ +++++++++++- ++++++++: "
write-host " .:-=. -+++++++==-:...+++++=: "
write-host " -+- -++. ++- =+++-:. "
write-host " "
write-host " "
write-host " "
write-host " :@@@@@# .%@@@@@# @@@@@@@@: @@@@@@@@@. ++- .+++++++: .=+++++- .+++ :++- "
write-host "+@@%+#@@% %@@@%#%@@@# @@@#+++- .++%@@@+++ ++- .+++:-=+++ .++++=-=+++: .++++. :++- "
write-host "*@@%=. %@@= #@@+ @@@- :@@@ ++- .++- =++ =++: -++: .+++++.:++- "
write-host " =@@@@@@- @@@ @@% @@@@@@% :@@@ ++- .++++++++- .+++ ++- .+++-+++++- "
write-host " :@@@: %@@= %@@+ @@@. :@@@ ++- .++++++- =++: =++. .+++ :++++- "
write-host "%@@%=+@@@. %@@@@%@@@@# @@@. :@@@ ++- .++- +++: =++++=++++: .+++ :+++- .:."
write-host " -%@@@@#. .*@@@@%* @@@. :@@@ ++: .++: -++- .-++++=: =++ :++: .:."
write-host " "
}