簡體   English   中英

為什么 Invoke-WebRequest 和 Invoke-RestMethod 同時失敗和成功?

[英]Why is Invoke-WebRequest and Invoke-RestMethod failing and succeeding at the same time?

我寫了一個小的 PowerShell 腳本來向服務器發送請求並返回一個簡單的 XML 結果。

PowerShell 腳本

$xml = "<?xml version='1.0' encoding='utf-8'?><Search><ID>278A87E1-1BC2-4E19-82E9-8BBE31D67D20</ID></Search>"
$response = Invoke-RestMethod -Method Post -Uri "http://localhost/search" -ContentType "application/xml" -Body $xml

就是這樣,非常簡單,我沒有理由認為它會失敗。 我還嘗試了使用Invoke-WebRequest的腳本,但都失敗了。 返回的錯誤是Invoke-RestMethod: Value cannot be null. Parameter name: name 奇怪的是,當我用Wireshark監視它時,我看到了連接,我看到了POST ,我看到了來自服務器的結果,一切看起來都很好,但是 cmdlet 說它失敗了(是的,返回碼是 200 ).

如果我使用-OutFile參數運行Invoke-WebRequest / Invoke-RestMethod ,它運行良好且沒有錯誤並將結果保存到指定文件; -OutVariable失敗以防萬一你想知道。

結果是一個 xml 文件,標頭指定它是 xml 並且 xml 的格式正確。

成功時的結果

<?xml version="1.0" encoding="UTF-8" ?>
<Result version="1.0" xmlns="urn:xmlns-org">
    <searchID>{278a87e1-1bc2-4e19-82e9-8bbe31d67d20}</searchID>
    <responseStatus>true</responseStatus>
    <responseStatusStrg>MORE</responseStatusStrg>
    <numOfMatches>40</numOfMatches>
</Result>

有誰知道為什么Invoke-XXX cmdlet 返回錯誤以及我可以做些什么來修復它? 同樣,當我使用-OutFile參數時,它工作得很好,即使它失敗了,我也可以在Wireshark中看到腳本和服務器之間的正確對話。

另外,如果我使用-Verbose它會告訴我以下內容:

VERBOSE: POST http://localhost/search with -1-byte payload
VERBOSE: received X-byte response of content type application/xml; charset="UTF-8"

其中X-byte是響應的實際大小,但根據發送到服務器的數據,每個響應明顯不同。 我只是覺得 cmdlet 失敗但說它收到了一個包含數據的響應並且它發送了一個-1-byte有效負載,這很奇怪。

我繼續查看了Invoke-WebRequest cmdlet代碼,並找出了為什么它失敗了這個特定的錯誤。

它在調用System.Globalization.EncodingTable.GetCodePageFromName失敗了。 編碼作為參數傳遞給該函數,並通過Content-Type標頭從cmdlet中檢索編碼。 在此服務器的情況下,Content-Type在響應中作為Content-Type: application/xml; charset="UTF-8"發送回Content-Type: application/xml; charset="UTF-8" Content-Type: application/xml; charset="UTF-8"

這樣做的問題是引號不是標准用於在charset包裝值,因此cmdlet將其解析為"UTF-8"而不是有效的UTF-8 cmdlet將"UTF-8"傳遞給函數,該函數拋出一個異常,指出提供的編碼無效。 這很好,並且如果這是最終例外中報告的內容會更有意義,但事實並非如此。

Microsoft.PowerShell.Commands.ContentHelper.GetEncodingOrDefault函數捕獲無效編碼異常,並在異常處理程序中再次調用GetEncoding但使用null參數導致參數name的最終ArgumentNullException

Microsoft.PowerShell.Commands.ContentHelper.GetEncodingOrDefault

internal static Encoding GetEncodingOrDefault(string characterSet)
{
  string name = string.IsNullOrEmpty(characterSet) ? "ISO-8859-1" : characterSet;
  try
  {
    return Encoding.GetEncoding(name);
  }
  catch (ArgumentException ex)
  {
    return Encoding.GetEncoding((string) null);
  }
}

在catch語句中調用GetEncoding會觸發GetCodePageFromName的以下代碼,該代碼本身是從GetEncoding

if (name==null) { 
    throw new ArgumentNullException("name");
}

PowerShell正在處理這個問題,因為從技術上講它是一個無效的值,但你認為他們會調用Trim("\\"")只是為了安全。

雖然這個線程已有多年歷史,但我是在 2022 年遇到同樣的錯誤“Invoke-RestMethod: Value cannot be null. Parameter name: name”訪問 API 以創建用戶時遇到的。 在我的例子中,Content-Type 是application/json (而不是上面 Vane 的問題中的application/xml )。 API POST 需要基本身份驗證。

在轉換為 Base64 之前,我對憑據進行了 UTF8 編碼,結果錯誤消失了。 鑒於上面 Vane 的 Content-Type 調查跟蹤了charset="UTF-8"的返回,這個 UTF8 編碼和錯誤的消失可能是相關的,盡管這只是我的猜測。

$username = "your_username"
$password = "your_password"
$credential = "${username}:${password}"
$credentialBytes = [System.Text.Encoding]::UTF8.GetBytes($credential)
$encodedCredential = [System.Convert]::ToBase64String($credentialBytes)
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Basic $encodedCredential")
$headers.Add("Content-Type", "application/json")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM