Private/Invoke-CICloudAPIRequest.ps1
function Invoke-CICloudAPIRequest(){ <# .SYNOPSIS This cmdlet will send a REST API call to the Cloud Director Cloud API Service and return an object containing the headers and the data payload to the caller. .PARAMETER URI The fully qualified URI of the vCloud API endpoint. .PARAMETER Method The HTTP Method to send for the API call .PARAMETER APIVersion The API version to be used for the API call .PARAMETER Data JSON data to be sent as the HTTP Payload in the API call. For a Get request the data is sent as a Query Parameter set. .PARAMETER Headers A Hashtable containing additional headers that should be passed during the API call. Any default headers will be overwritten. .PARAMETER InFile Optionally for a file upload the file to upload .NOTES This cmdlet obeys the ProxyPolicy and InvalidCertificateAction parameters set in the VMWare PowerCLI Configuration. There is a limitation for PowershellCore that at the cmdlet can only be used with the "UseSystemProxy" policy on Windows netsh winhttp show proxy settings; this will be changed in future AUTHOR: Adrian Begg LASTEDIT: 2019-12-10 VERSION: 1.0 #> Param( [Parameter(Mandatory=$True)] [ValidateScript({[system.uri]::IsWellFormedUriString($_,[System.UriKind]::Absolute)})] [string] $URI, [Parameter(Mandatory=$True)] [ValidateSet("Get","Put","Post","Delete","Patch")] [string] $Method, [Parameter(Mandatory=$True)] [ValidateSet(34,33,32,31,30)] [int] $APIVersion, [Parameter(Mandatory=$False)] [ValidateSet("Legacy","CloudAPI")] [string] $APIType = "CloudAPI", [Parameter(Mandatory=$False)] [ValidateSet("XML","JSON")] [string] $LegacyAPIDataType = "XML", [Parameter(Mandatory=$False)] [ValidateNotNullorEmpty()] [string] $CustomContentType, [Parameter(Mandatory=$False)] [ValidateNotNullorEmpty()] $Data, [Parameter(Mandatory=$False)] [ValidateNotNullorEmpty()] $InFile, [Parameter(Mandatory=$False)] [Hashtable] $Headers ) # Validate the environment is ready based on the input parameters if(!(Test-CIServerConnection)){ Break } # Construct the headers for the API call $APIHeaders = @{ 'x-vcloud-authorization' = $global:DefaultCIServers.SessionId } # Add the API Version Header (CloudAPI did not exist before API version 30) if($APIType -eq "CloudAPI"){ if($APIVersion -lt 30){ throw "The provided API Version is not supported by this cmdlet. Please check the compatibility and try again" } else { $APIHeaders.Add("Content-Type","application/json") $APIHeaders.Add("Accept","application/json;version=$APIVersion.0") } } else { # Legacy API generally uses XML however only can use a JSON header if($LegacyAPIDataType -eq "XML"){ $APIHeaders.Add("Content-Type","application/*+xml") $APIHeaders.Add("Accept","application/*+xml;version=$APIVersion.0") } elseif($LegacyAPIDataType -eq "JSON"){ $APIHeaders.Add("Content-Type","application/*+json") $APIHeaders.Add("Accept","application/*+json;version=$APIVersion.0") } } if($PSBoundParameters.ContainsKey("CustomContentType")){ $APIHeaders."Content-Type" = $CustomContentType } # Check if any custom headers have been provided and if they have set them if($Headers.Count -ne 0){ foreach($Key in $Headers.Keys){ $APIHeaders.$Key = $Headers.$Key } } # Create a Hashtable with base paramters to use for splatting to Invoke-WebRequest $HashInvokeArguments = @{ Uri = $URI Method = $Method Headers = $APIHeaders } # Next check the PowerCLI Proxy policy to determine if what Proxy Policy should be used for the API call and set accordingly if((Get-PowerCLIConfiguration -Scope "User" | Select-Object ProxyPolicy).ProxyPolicy -eq "NoProxy") { $HashInvokeArguments.Add("NoProxy",$true) } elseif((Get-PowerCLIConfiguration -Scope "User" | Select-Object ProxyPolicy).ProxyPolicy -eq "UseSystemProxy") { # Check the PowerShell edition first if($Global:PSEdition -eq "Desktop"){ $Proxy = ([System.Net.WebRequest]::GetSystemWebProxy()).GetProxy($URI) $HashInvokeArguments.Add("Proxy",$Proxy.AbsoluteUri) $HashInvokeArguments.Add("ProxyUseDefaultCredentials",$true) } elseif($Global:PSEdition -eq "Core") { # For PowerShell Core you can not use the [System.Net.WebProxy]::GetDefaultProxy() or [System.Net.WebRequest]::GetSystemWebproxy() static method as its not supported # Really not happy with this implementation but temporary until can write a better handler or support is added for GetDefaultProxy static method $Proxy = Get-WinHttpProxy if($Proxy.'Winhttp proxy' -ne "Direct Access"){ [string] $ProxyString = "http://$($Proxy.'Winhttp proxy')" $HashInvokeArguments.Add("Proxy",$ProxyString) $HashInvokeArguments.Add("ProxyUseDefaultCredentials",$true) } } } # Check if the Certificate Check should be performed and add the argument if not if((Get-PowerCLIConfiguration -Scope "User" | Select-Object InvalidCertificateAction).InvalidCertificateAction -eq "Ignore") { $HashInvokeArguments.Add("SkipCertificateCheck",$true) } # Check if data has been provided if($PSBoundParameters.ContainsKey("Data")){ $HashInvokeArguments.Add("Body", $Data) } # Check if we are sending a file if($PSBoundParameters.ContainsKey("Data")){ $HashInvokeArguments.Add("InFile", $InFile) } # Now try and make the API call try{ $Request = Invoke-WebRequest @HashInvokeArguments $objResponse = New-Object System.Management.Automation.PSObject $objResponse | Add-Member Note* Headers $Request.Headers if($null -ne $Request.Content){ try{ $objResponse | Add-Member Note* JSONData (ConvertFrom-JSON ($Request.Content)) } catch { # For non-JSON payloads/check if an encloding problem has occurred try{ $objResponse | Add-Member Note* JSONData (ConvertFrom-JSON ([System.Text.Encoding]::Ascii.GetString($Request.Content))) } catch { $objResponse | Add-Member Note* RawData $Request.Content } } } $objResponse } catch { if($_.Exception.Response.StatusCode -eq "Unauthorized"){ throw [System.UnauthorizedAccessException] "An Unauhorized Exception was thrown attempting to make the API call to $URI. Please check that you have the required permissions to execute this call and that you have a current connected session." } else { throw "An error occurred making an API call to $URI. Exception details: $($_.Exception)" } } } |