source

Powershell Invoke-Rest 메서드가 http 500 코드 응답 본문을 반환하도록 하는 방법

nicesource 2023. 8. 2. 09:12
반응형

Powershell Invoke-Rest 메서드가 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-rest 메서드 : 원격 서버에서 오류를 반환했습니다. (500) 내부 서버 오류입니다.줄에:1 문자:9...

아래의 피들러 트레이스

HTTP/1.1500 내부 서버 오류 연결: 종료 날짜:2013년 9월 12일 17:35:00 GMT 서버: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 EnvApi-Version: 2.0,2.0 EnvApi-Remaining-Calls: 994,994 EnvApi-Remaining-Interval: 2684,2684 캐시 제어: no-Cache Pragma: no-Cache 만료 없음: text-type: text/csvset= charutf-8

{"errorNumber":0,message":"현재 사용자에게는 'CustomFieldTemplate' 테이블에서 데이터를 검색할 권한이 없습니다."}

다른 답변은 응답을 제공하지만, 헤더뿐만 아니라 응답의 실제 본문을 가져오려면 추가 단계가 필요합니다.다음은 스니펫입니다.

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

오래된 스레드이지만 cmdlet Invoke-WebRequest 및 Invoke-RestMethod 문제에 대한 답변입니다.

이것은 꽤 오랫동안 저를 괴롭혔습니다.모든 4xx 및 5xx 응답이 예외를 생성하므로 예외를 포착해야 합니다. 그러면 여기서 응답을 추출할 수 있습니다.다음과 같이 사용합니다.

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

이제 $resp는 항상 당신이 좋아하는 모든 것을 포함하고 있습니다.

이 솔루션은 더 이상 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($_)
}

제 문제에 대한 답을 검색하던 중 이 스레드를 발견했습니다.

이러한 솔루션은 저에게 효과적이었지만, 다음 두 가지를 새로 추가해야 했습니다.

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

감사합니다!

저는 Invoke-RestMethod를 독점적으로 사용해 왔으며 Invoke-WebRequest의 래퍼일 수 있으므로 다음 정보가 유용할 수 있습니다.

예외를 탐지한 다음 이렇게 응답에서 응답 스트림을 가져와야 합니다.

    try
    {
        $response = Invoke-RestMethod Method Get uri "$($uri)" -Headers $headers
        return $response
    }
    catch
    {
        Write-Host "Exception details: "
        $e = $_.Exception
        Write-Host ("`tMessage: " + $e.Message)
        Write-Host ("`tStatus code: " + $e.Response.StatusCode)
        Write-Host ("`tStatus description: " + $e.Response.StatusDescription)

        Write-Host "`tResponse: " -NoNewline
        $memStream = $e.Response.GetResponseStream()
        $readStream = New-Object System.IO.StreamReader($memStream)
        while ($readStream.Peek() -ne -1) {
            Write-Host $readStream.ReadLine()
        }
        $readStream.Dispose();
    }

참조: https://social.technet.microsoft.com/Forums/windowsserver/en-US/7d838d53-bfd5-4706-b0df-c4bee2d00412/using-memorystream-and-textreader

.$_.ErrorDetails.Message원래 응답 본문이 아닙니다.HTML 태그 제거 정규식을 사용하여 응답을 github 링크를 보다 쉽게 읽을 수 있습니다.스트림은 1535번 라인에 배치되므로 현재 원래 응답 본문을 검색할 수 있는 방법이 없습니다.

방법은 입니다.HttpClient사용하는 대신 원래 응답을 얻습니다.Invoke-WebRequestcmdlet

$url = "http://localhost"
$client = [System.Net.Http.HttpClient]::new()
$request = [System.Net.Http.HttpRequestMessage]::new([System.Net.Http.HttpMethod]::Post, $url)
$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

파워셸 코어 깃허브 문제는 여기에 있습니다.

이것은 구글의 첫 번째 히트작 중 하나이기 때문에, 여기 파워셸 코어 6.0.0/7.0.0에 대한 답이 있습니다.

및 는 Invoke-RestMethod 및 Invoke-WebRequest를 지원합니다.-SkipHttpErrorCheck스위치:

이 매개 변수로 인해 cmdlet은 HTTP 오류 상태를 무시하고 응답을 계속 처리합니다.오류 응답은 성공한 것처럼 파이프라인에 기록됩니다.

이 스위치를 사용하는 경우 Cmdlet은 실패한 상태 코드가 수신될 때 오류를 발생시키지 않습니다.


에는 이제 변수 Invoke-RestMethod가 .-StatusCodeVariable그리고.-ResponseHeadersVariable하는 데 할 수 .


-ResponseHeadersVariable 및 v6.0.0에 되었습니다.-SkipHttpErrorCheck/ResponseStatusVariable0v7.0.0에서

언급URL : https://stackoverflow.com/questions/18771424/how-to-get-powershell-invoke-restmethod-to-return-body-of-http-500-code-response

반응형