PowerShell-V5 Invoke-Webrequest adding 2 headers a

2019-07-17 14:43发布

问题:

I am trying create a script that will automate the upgrade of NSX using powershell and invoke-webrequest to utilize the API calls of the NSX Manager. I am doen with the script but some part of the script i need to check and match on some data in the respond. as a matter of fact the NSX API response will 90% be in xml format but some times it can be in json. If the response came in json format my matching will not work and also some parts of the script will not work as it is expecting xml and can not convert json to xml.

as i understand that starting from powershell v4 you can add the accept header but the problem is that i am already using one header for authorization.

Is it possible to add multiple headers in the invoke-webrequest in powershell and if yes how would it be.

Below is a part of the script that i have which will check the current version of the deployed NSX. so it will match on a value in the response which will show the version.

#Variables to be used within the script.
[CmdletBinding()]
$NSXUsername = "admin"
$NSXPassword = "VMware1!"
$uriP = "https://HQ-NSX-01a.nsx.gss"


# Start time.
$startclock = (Get-Date)
Write-Host -BackgroundColor:Black -ForegroundColor:Green "Hello"
Write-Host -BackgroundColor:Black -ForegroundColor:Green "This script will help you to automate a full NSX environment deployment"
Write-Host -BackgroundColor:Black -ForegroundColor:Green "FULL NSX Tier Deployment for Single-VC is starting, This Deployment proccess will take an average of 60 min
========================================================================================
                                 "




# Create NSX authorization string and store in $head and used in API Calls
# $nsxcreds = New-Object System.Management.Automation.PSCredential $NSXUsername,$NSXPassword
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUsername + ":" + $NSXPassword))
$head = @{"Authorization"="Basic $auth"}

# Allow untrusted SSL certs else will error out
    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;
            }
        }
"@
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy


################
#Start of Script
################

###########################################
# Checking the current deployed NSX Version
###########################################

    Write-Host -BackgroundColor:Black -ForegroundColor:Green "      Checking the current deployed version of the NSX
                             "


    $r = Invoke-WebRequest -Uri "$uriP/api/1.0/appliance-management/global/info" -Method:Get -Headers $head -ContentType "application/xml" -ErrorAction:Stop -TimeoutSec 60
    $nsxbn = ([xml]$r.Content).globalInfo.versionInfo.buildNumber

    if ($nsxbn -match "2691049") {$nsxcv = "6.1.4"}
    elseif ($nsxbn -match "3102213") {$nsxcv = "6.1.5"}
    elseif ($nsxbn -match "3615148") {$nsxcv = "6.1.6"}
    elseif ($nsxbn -match "3949567") {$nsxcv = "6.1.7"}
    elseif ($nsxbn -match "2986609") {$nsxcv = "6.2.0"}
    elseif ($nsxbn -match "3300239") {$nsxcv = "6.2.1"}
    elseif ($nsxbn -match "3496286") {$nsxcv = "6.2.1a"}
    elseif ($nsxbn -match "3604087") {$nsxcv = "6.2.2"}
    elseif ($nsxbn -match "3638734") {$nsxcv = "6.2.2a"}
    elseif ($nsxbn -match "3755950") {$nsxcv = "6.2.2b"}
    elseif ($nsxbn -match "3979471") {$nsxcv = "6.2.3"}
    elseif ($nsxbn -match "4167369") {$nsxcv = "6.2.3a"}
    elseif ($nsxbn -match "4287432") {$nsxcv = "6.2.3b"}
    elseif ($nsxbn -match "4292526") {$nsxcv = "6.2.4"}
    elseif ($nsxbn -match "4818372") {$nsxcv = "6.2.5"}
    elseif ($nsxbn -match "4977495") {$nsxcv = "6.2.6"}
    elseif ($nsxbn -match "5007049") {$nsxcv = "6.3.0"}
    elseif ($nsxbn -match "5124716") {$nsxcv = "6.3.1"}
    else {
    Write-host -BackgroundColor:Black -ForegroundColor:Red "       Unable to retrieve the NSX version, This is either due to the current version is unknown to this script or the NSX Manager is powered off. Please check and try again."
    exit
    }

    Write-Host -BackgroundColor:Black -ForegroundColor:Green "      Current version of NSX deployed and to be upgraded is $nsxcv
                             "

The response if it is in xml format would as below and i will match on the version.

<?xml version="1.0" encoding="UTF-8"?>
<globalInfo>
    <currentLoggedInUser>admin</currentLoggedInUser>
    <versionInfo>
        <majorVersion>6</majorVersion>
        <minorVersion>1</minorVersion>
        <patchVersion>5</patchVersion>
        <buildNumber>3102213</buildNumber>    <<<--- this is my match
    </versionInfo>
</globalInfo>

The above script will just work fine if the response is in xml format (which 90% of the time) but if it is json i will get the below error and the script will exit.

Cannot convert value "{"currentLoggedInUser":"admin","versionInfo":{"majorVersion":"6","minorVersion":"1","patchVersion":"5","buildNumber":"3102213"}}" 
to type "System.Xml.XmlDocument". Error: "The specified node cannot be inserted as the valid child of this node, because the specified node is the wrong 
type."
At C:\Users\Administrator\Desktop\Scripts  Folder\NSX-Auto-Upgrade-Single.ps1:68 char:2
+     $nsxbn = ([xml]$r.Content).globalInfo.versionInfo.buildNumber
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastToXmlDocument

your help is much appreciated.

Thank you.

回答1:

I gather that you intend to add multiple headers to a REST API call through powershell. Instead of adding headers like this,

$head = @{"Authorization"="Basic $auth"}

Invoke-WebRequest -Uri "$uriP/api/1.0/appliance-management/global/info" -Method:Get -Headers $head -ContentType "application/xml" -ErrorAction:Stop -TimeoutSec 60

You can add them like this

Invoke-WebRequest -Uri "$uriP/api/1.0/appliance-management/global/info" -Method:Get -Headers @{"Authorization"="Basic $auth"; "Accept"="application/xml"} -ContentType "application/xml" -ErrorAction:Stop -TimeoutSec 60

Source : http://community.idera.com/powershell/ask_the_experts/f/learn_powershell_from_don_jones-24/20461/invoke-restmethod-passing-header-values



回答2:

I have found the answer for this and posting it here.

If you changed the header part to add more header like below it will work:

$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUsername + ":" + $NSXPassword))
$head = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$head = @{}
$head.Add("Authorization","Basic $auth")
$head.Add("Accept","application/xml")

So when i added this to my script it worked fine and also to confirm it i have did it once with accept"application/xml" and another with accept"application/json" and printed the output.

So first accept"application/xml"

Script:

#Variables to be used within the script.
[CmdletBinding()]
$NSXUsername = "admin"
$NSXPassword = "VMware1!"
$uriP = "https://HQ-NSX-01a.nsx.gss"

# Start time.
$startclock = (Get-Date)
# Create NSX authorization string and store in $head and used in API Calls
# $nsxcreds = New-Object System.Management.Automation.PSCredential $NSXUsername,$NSXPassword
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUsername + ":" + $NSXPassword))
$head = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$head = @{}
$head.Add("Authorization","Basic $auth")
$head.Add("Accept","application/xml")
# Allow untrusted SSL certs else will error out
    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;
            }
        }
"@
    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

$r = Invoke-WebRequest -Uri "$uriP/api/1.0/appliance-management/global/info" -Method:Get -Headers $head -ContentType "application/xml" -ErrorAction:Stop -TimeoutSec 60


    Write-host -BackgroundColor:Black -ForegroundColor:Red "$r"

i get the below:

<?xml version="1.0" encoding="UTF-8"?>
<globalInfo><currentLoggedInUser>admin</currentLoggedInUser><versionInfo><majorVersion>6</majorVersion><minorVersion>1</minorVersion><patchVersion>5</patchVersion><
buildNumber>3102213</buildNumber></versionInfo></globalInfo>

if i changed the header variable to the below (which is accepting only json):

$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUsername + ":" + $NSXPassword))
$head = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$head = @{}
$head.Add("Authorization","Basic $auth")
$head.Add("Accept","application/json")

i get the below:

{"currentLoggedInUser":"admin","versionInfo":{"majorVersion":"6","minorVersion":"1","patchVersion":"5","buildNumber":"3102213"}}

So based on that the solution to my issue is to change the header variable in the original script (posted in the question above) to the below and this will work fine:

$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NSXUsername + ":" + $NSXPassword))
$head = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$head = @{}
$head.Add("Authorization","Basic $auth")
$head.Add("Accept","application/xml")