如何让Powershell Invoke-Restmethod返回http 500代码响应的主体

问题描述 投票:29回答:5

Invoke-RestMethod调用仅返回下面非常无用的异常,并且(据我所知)不允许您收集正文内容(fiddler跟踪结果中显示的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)内部服务器错误。在行:1字符:9 ...

Fiddler跟踪如下

HTTP / 1.1 500内部服务器错误连接:关闭日期:星期四,2013年9月12日17:35:00 GMT服务器:Microsoft-IIS / 6.0 X-Powered-By:ASP.NET X-AspNet-版本:2.0.50727 EnvApi-版本:2.0,2.0 EnvApi-Remaining-Calls:994,994 EnvApi-Remaining-Interval:2684,2684 Cache-Control:no-cache Pragma:no-cache Expires:-1 Content-Type:text / csv;字符集= utf-8的

{“errorNumber”:0,“message”:“当前用户无权从表'CustomFieldTemplate'”中检索数据

powershell powershell-v3.0
5个回答
24
投票

虽然是旧线程,但这里是cmdlet Invoke-WebRequest和Invoke-RestMethod问题的答案。

这一次困扰了我很长一段时间。由于所有4xx和5xx响应都生成异常,您必须捕获该异常,然后您可以从那里提取响应。像这样使用它:

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

现在$ resp总是包含你喜欢的一切。


79
投票

另一个答案确实可以为您提供响应,但您需要一个额外的步骤来获取响应的实际主体,而不仅仅是标题。这是一个片段:

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();
}

12
投票

搜索我的问题的答案我找到了这个帖子。

这些解决方案对我有用,但我不得不添加两个新行:

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

谢谢!


12
投票

此解决方案不再适用于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($_)
}

0
投票

请注意,作为Florial Feldhaus对答案提供者的延伸,$_.ErrorDetails.Message不是最初的回复机构。 HTML标记删除正则表达式用于使响应更容易阅读github link。由于流设置在线1535上,因此目前无法检索原始响应体。

解决方法是使用dotnet HttpClient获取原始响应,而不是使用Invoke-WebRequest cmdlet

$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

© www.soinside.com 2019 - 2024. All rights reserved.