web-dev-qa-db-ja.com

Powershell Invoke-Restmethodを取得してHTTP 500コード応答の本文を返す方法

Invoke-RestMethod呼び出しは、以下の非常に役に立たない例外のみを返し、本文の内容(フィドラートレース結果に表示されるJSONオブジェクト)の収集を許可しません。もしそうなら、これはかなり悪い実装のようです。なぜなら、http 500の定義は、クライアントが応答の本文を返してトラブルシューティングを支援する必要があるためです...何か不足していますか?

invoke-restmethod -method Post -uri "https://api-stage.enviance.com/ver2/EqlService.svc/eql" -Body (ConvertTo-Json $eqlhash)  -Headers @{"Authorization"="Enviance $session"}

invoke-restmethod:リモートサーバーがエラーを返しました:(500)Internal Server Error。 1行目:char:9 ...

以下のフィドラートレース

HTTP/1.1 500内部サーバーエラー接続:終了日:2013年9月12日(木)17:35:00 GMTサーバー:Microsoft-IIS/6.0 X-Powered-By:ASP.NET X-AspNet-Version:2.0.50727 EnvApi-バージョン:2.0,2.0 EnvApi-Remaining-Calls:994,994 EnvApi-Remaining-Interval:2684,2684 Cache-Control:no-cacheプラグマ:no-cache Expires:-1 Content-Type:text/csv; charset = utf-8

{"errorNumber":0、 "message": "現在のユーザーには、テーブル 'CustomFieldTemplate'からデータを取得する権限がありません"}

31
JorgeSandoval

古いスレッドですが、ここではコマンドレットInvoke-WebRequestおよびInvoke-RestMethodの問題に対する答えを示します。

これは長い間私を悩ませてきました。 4xxおよび5xxの応答はすべて例外を生成しているため、その応答をキャッチする必要があります。その後、そこから応答を抽出できます。次のように使用します。

$resp = try { Invoke-WebRequest ... } catch { $_.Exception.Response }

現在、$ respには常に好きなものがすべて含まれています。

24
Anonymous

もう1つの答えは応答を取得しますが、ヘッダーだけでなく、応答の実際の本文を取得するために追加の手順が必要です。以下がスニペットです。

try {
        $result = Invoke-WebRequest ...
}
catch {
        $result = $_.Exception.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($result)
        $reader.BaseStream.Position = 0
        $reader.DiscardBufferedData()
        $responseBody = $reader.ReadToEnd();
}
79
Noah Stahl

このソリューションは、PowerShell 6では動作しなくなりました-GetResponseStream()をサポートしません。代わりに使用

try {
    $result = Invoke-WebRequest ...
}
catch {
    $_.ErrorDetails.Message
}

PowerShell 6以前をサポートする短いヘルパー関数を作成しました。

function ParseErrorForResponseBody($Error) {
    if ($PSVersionTable.PSVersion.Major -lt 6) {
        if ($Error.Exception.Response) {  
            $Reader = New-Object System.IO.StreamReader($Error.Exception.Response.GetResponseStream())
            $Reader.BaseStream.Position = 0
            $Reader.DiscardBufferedData()
            $ResponseBody = $Reader.ReadToEnd()
            if ($ResponseBody.StartsWith('{')) {
                $ResponseBody = $ResponseBody | ConvertFrom-Json
            }
            return $ResponseBody
        }
    }
    else {
        return $Error.ErrorDetails.Message
    }
}

try {
    $result = Invoke-WebRequest ...
}
catch {
    ParseErrorForResponseBody($_)
}
12

問題の答えを探して、このスレッドを見つけました。

これらのソリューションは私にとってはうまくいきましたが、2つの新しい行を追加する必要がありました。

 $reader.BaseStream.Position = 0
 $reader.DiscardBufferedData()

ありがとう!

12
Cisco Cabe

Florial Feldhausによる回答プロバイダーの拡張として、$_.ErrorDetails.Messageは元の応答本文ではないことに注意してください。 HTMLタグ削除正規表現は、応答を読みやすくするために使用されます github link 。ストリームは1535行目に配置されているため、現在、元の応答本文を取得する方法はありません。

回避策は、Invoke-WebRequestコマンドレットを使用する代わりに、ドットネットHttpClientを使用して元の応答を取得することです。

$url = "http://localhost"
$client = [System.Net.Http.HttpClient]::new()
$request = [System.Net.Http.HttpRequestMessage]::new()
$request.Content = [System.Net.Http.StringContent]::new("Hello World", [System.Text.Encoding]::UTF8, "plain/text")

$result = $client.SendAsync($request).GetAwaiter().GetResult()
$content = $result.Content.ReadAsStringAsync().GetAwaiter().GetResult()

Write-Verbose $content -Verbose

Powershellコアgithubの問題は here

0
Thomas