我如何获得一个Web请求的主体,从调用-RestMethod返回400错误的请求我如何获得一个Web

2019-05-12 07:14发布

当我运行下面的语句

Invoke-RestMethod "https://api.mysite.com/the/endpoint" `
    -Body (ConvertTo-Json $data) `
    -ContentType "application/json" `
    -Headers $DefaultHttpHeaders `
    -Method Post

端点返回400 Bad Request ,这将导致PowerShell将显示以下不那么有用信息:

Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At line:1 char:1
+ Invoke-WebRequest "https://api.mysite.com/the/endpoint" -Body  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

我如何获得响应的身体,这可能会告诉我什么是错的我发送的请求?

Answer 1:

据调用-RestMethod文档,小命令可以返回根据它接收到的内容不同的类型。 Assing小命令输出给一个变量( $resp = Invoke-RestMethod (...)然后检查如果类型是HtmlWebResponseObject$resp.gettype() 然后你就会在您的处置许多特性,如BaseResponse,内容及的StatusCode。

如果$resp是一些其他类型(字符串,psobject并极有可能为空在这种情况下),似乎是错误信息The remote server returned an error: (400) Bad Request是响应主体,从HTML只提(我测试了这个关于我的一些方法),甚至截断。 如果要提取它,使用通用参数来存储错误信息运行cmdlet: Invoke-RestMethod (...) -ErrorVariable RespErr ,你就会有它在$RespErr变量。

编辑:

好吧,我知道了,这是很明显的:)。 调用-RestMethod抛出一个错误,所以让我们正好赶上它:

try{$restp=Invoke-RestMethod (...)} catch {$err=$_.Exception}
$err | Get-Member -MemberType Property

  TypeName: System.Net.WebException

    Name           MemberType Definition
    ----           ---------- ----------
    Message        Property   string Message {get;}
    Response       Property   System.Net.WebResponse Response {get;}
    Status         Property   System.Net.WebExceptionStatus Status {get;}

这里有你所需要的,尤其是在WebResponse对象。 我列出了3个属性是吸引眼球,还有更多。 此外,如果你存储$_ ,而不是$_.Exception可能会有一些性能的PowerShell已经提取了你,但我并不指望什么比更有意义.Exception.Response



Answer 2:

有使用PowerShell一个已知的问题Invoke-WebRequestInvoke-RestMethod其中壳吃响应体时的状态代码是错误(或4XX 5XX)。 听起来像是你正在寻找只是这种方式被蒸发JSON内容。 您可以使用您的catch块获取响应正文$_.Exception.Response.GetResponseStream()

    try {
    Invoke-RestMethod "https://api.mysite.com/the/endpoint" `
        -Body (ConvertTo-Json $data) `
        -ContentType "application/json" `
        -Headers $DefaultHttpHeaders `
        -Method Post
    }
    catch {
        $streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
        $ErrResp = $streamReader.ReadToEnd() | ConvertFrom-Json
        $streamReader.Close()
    }

    $ErrResp


Answer 3:

$ RespErr将有关于错误请求的详细信息,在我的情况下,其

$responce = Invoke-RestMethod -Uri https://localhost:44377/explore/v2/Content -Method Post -Body $PostData -Headers $header -ErrorVariable RespErr;

$ RespErr;

{ "error":{ "code":"","message":"The FavoriteName field is required." } }

它看起来像它只能在本地主机,我想用我的实际的服务器没有奏效。

另一种方式是尝试这个

    try{
$response = ""
$response = Invoke-WebRequest -Uri https://contentserverint-mhdev.azurewebsites.net/apis/explore/v2/Content?overwrite=true -Method Post -Body $PostData -Headers  $header -ErrorVariable RespErr 
#$response = Invoke-RestMethod -Uri https://localhost:44377/explore/v2/Content?overwrite=true -Method Post -Body $PostData -Headers  $header -ErrorVariable RespErr 
Write-Host "Content created with url="$response.value[0] 

}
catch [System.Net.WebException] {   
        $respStream = $_.Exception.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($respStream)
        $respBody = $reader.ReadToEnd() | ConvertFrom-Json
        $respBody;
 }


Answer 4:

如果你只是响应后StatusCodeContent这里没有很多杂乱的try / catch和响应流的人工抄表的解决这一问题的新方法:

# Place the trap within your chosen scope (e.g. function or script)
trap [Net.WebException] { continue; }

# Exceptions are no longer thrown here
$response = Invoke-WebRequest $endpoint

# Check if last command failed
if (!$?)
{   
    # $error[0] now contains the ErrorRecord of the last error (in this case from Invoke-WebRequest)
    # Note: $response should be null at this point

    # Due to the magic of Microsoft.PowerShell.Commands.InvokeWebRequestCommand.WebCmdletWebResponseException
    # we can get the response body directly from the ErrorDetails field
    $body = $error[0].ErrorDetails.Message

    # For compatibility with $response.StatusCode lets cast to int    
    $statusCode = [int] $error[0].Exception.Response.StatusCode
}

据我所知道的, ErrorRecord.ErrorDetails.Message包含准确相当于Microsoft.PowerShell.Commands.WebResponseObject.Content将得到退还给你的一个成功调用属性Invoke-WebRequest ,只是不必的麻烦做一切GetResponseStream()爵士。



Answer 5:

对我来说,只有在一个纠缠背景下工作过,流位置设置为0时,阅读它之前。

        $statusCode = $null
        $responseBody = $null
        try {
            $response = Invoke-RestMethod -Method GET -Uri "$($apiPrefix)$($operation)" -Headers $headers
            }
        catch [System.Net.WebException] {
            $statusCode = $_.Exception.Response.StatusCode
            $respStream = $_.Exception.Response.GetResponseStream()
            $reader = New-Object System.IO.StreamReader($respStream)
            $reader.BaseStream.Position = 0
            $responseBody = $reader.ReadToEnd() | ConvertFrom-Json
        }
        $statusCode | Should Be $Expected
        $responseBody | Should Not Be $null


文章来源: How do I get the body of a web request that returned 400 Bad Request from Invoke-RestMethod