Powershell-Webanforderung ohne Ausnahme bei 4xx / 5xx

82

Ich schreibe ein Powershell-Skript, das eine Webanforderung stellen und den Statuscode der Antwort überprüfen muss.

Ich habe versucht, dies zu schreiben:

$client = new-object system.net.webclient

$response = $client.DownloadData($url)

so gut wie das:

$response = Invoke-WebRequest $url

Wenn die Webseite jedoch einen Statuscode enthält, der kein Erfolgsstatuscode ist, löst PowerShell eine Ausnahme aus, anstatt mir das eigentliche Antwortobjekt zu geben.

Wie kann ich den Statuscode der Seite erhalten, auch wenn sie nicht geladen werden kann?

jcarpenter2
quelle
Dies funktionierte für mich docs.microsoft.com/en-us/powershell/module/… Beispiel 7: Abfangen nicht erfolgreicher Nachrichten von Invoke-WebRequest
user3520245

Antworten:

121

Versuche dies:

try { $response = Invoke-WebRequest http://localhost/foo } catch {
      $_.Exception.Response.StatusCode.Value__}

Es ist eine Art Mist, dass dies eine Ausnahme auslöst, aber so ist es nun mal.

Update per Kommentar

Um sicherzustellen, dass solche Fehler immer noch eine gültige Antwort zurückgeben, können Sie diese Ausnahmen vom Typ erfassen WebExceptionund die zugehörigen abrufen Response.

Da die Antwort auf die Ausnahme vom Typ ist System.Net.HttpWebResponse, während die Antwort von einem erfolgreichen Invoke-WebRequestAufruf vom Typ ist Microsoft.PowerShell.Commands.HtmlWebResponseObject, müssen wir die erfolgreichen Antworten verwenden BaseResponse, die ebenfalls vom Typ sind, um einen kompatiblen Typ aus beiden Szenarien zurückzugeben System.Net.HttpWebResponse.

Der Statuscode dieses neuen Antworttyps ist eine Aufzählung vom Typ [system.net.httpstatuscode]und keine einfache Ganzzahl. Sie müssen ihn also explizit in int konvertieren oder Value__wie oben beschrieben auf seine Eigenschaft zugreifen , um den numerischen Code zu erhalten.

#ensure we get a response even if an error's returned
$response = try { 
    (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseResponse
} catch [System.Net.WebException] { 
    Write-Verbose "An exception was caught: $($_.Exception.Message)"
    $_.Exception.Response 
} 

#then convert the status code enum to int by doing this
$statusCodeInt = [int]$response.BaseResponse.StatusCode
#or this
$statusCodeInt = $response.BaseResponse.StatusCode.Value__
Keith Hill
quelle
5
Danke, das hat funktioniert. Mir war nicht klar, dass Sie nur über das Exception-Objekt auf das Response-Objekt zugreifen können.
jcarpenter2
1
Ja, es war etwas schwierig, zur tatsächlichen Codenummer zu gelangen. :-)
Keith Hill
Ich gehe zu diesem Code von Chris Wahl, wahlnetwork.com/2015/02/19/…
FoxDeploy
11
Ein etwas besserer Weg: $ response = try {Invoke-WebRequest localhost / foo } catch {$ _. Exception.Response} Auf diese Weise erhalten Sie in beiden Fällen etwas in der Variablen $ response. Beachten Sie jedoch, dass ein Fehler eine HtmlWebResponse zurückgibt, ein Erfolg jedoch ein HtmlWebResponseObject zurückgibt. Insbesondere der StatusCode auf diesen sind verschiedene Typen (seufz ..)
Rob Cannon
4
Ein paar kleine Änderungen an Robs großartigem Vorschlag, um das Problem mit verschiedenen Typen zu vermeiden : $response = try { (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseRequest } catch [System.Net.WebException] { $_.Exception.Response }. Das Abrufen BaseRequeststellt sicher, dass wir sowohl in Erfolgs- als auch in Fehlerszenarien eine erhalten HttpWebReqponse. Durch das Hinzufügen wird [System.Net.WebException]sichergestellt, dass nur relevante Ausnahmen auf diese Weise erfasst werden und andere Arten von Problemen nicht versehentlich beseitigt werden.
JohnLBevan
6

Seit Powershell Version 7.0 Invoke-WebRequesthaben -SkipHttpErrorCheckSchalterparameter.

-SkipHttpErrorCheck

Dieser Parameter bewirkt, dass das Cmdlet den HTTP-Fehlerstatus ignoriert und die Antworten weiter verarbeitet. Die Fehlerantworten werden so in die Pipeline geschrieben, als ob sie erfolgreich wären.

Dieser Parameter wurde in PowerShell 7 eingeführt.

docs Pull-Anfrage

Mariusz Pawelski
quelle
0

-SkipHttpErrorCheck ist die beste Lösung für PowerShell 7+. Wenn Sie dies jedoch noch nicht verwenden können, finden Sie hier eine einfache Alternative, die für interaktive Poweshell-Befehlszeilensitzungen hilfreich ist.

Wenn Sie eine Fehlerbeschreibung für eine 404-Antwort sehen, dh

Der Remote-Server hat einen Fehler zurückgegeben: (404) Nicht gefunden.

Dann können Sie den 'letzten Fehler' in der Befehlszeile sehen, indem Sie Folgendes eingeben:

$Error[0].Exception.Response.StatusCode

Oder

$Error[0].Exception.Response.StatusDescription

Oder was auch immer Sie sonst noch vom `Response'-Objekt wissen möchten.

DaveC
quelle