Solicitud web de Powershell sin lanzar una excepción en 4xx / 5xx

82

Estoy escribiendo un script de PowerShell que debe realizar una solicitud web e inspeccionar el código de estado de la respuesta.

He intentado escribir esto:

$client = new-object system.net.webclient

$response = $client.DownloadData($url)

tan bien como esto:

$response = Invoke-WebRequest $url

pero siempre que la página web tiene un código de estado que no es un código de estado de éxito, PowerShell sigue adelante y lanza una excepción en lugar de darme el objeto de respuesta real.

¿Cómo puedo obtener el código de estado de la página incluso cuando no se carga?

jcarpenter2
fuente
Esto funcionó para mí docs.microsoft.com/en-us/powershell/module/… Ejemplo 7: Capture mensajes de no éxito de Invoke-WebRequest
user3520245

Respuestas:

121

Prueba esto:

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

Es una especie de fastidio que esto arroje una excepción, pero así es.

Actualizar por comentarios

Para asegurarse de que dichos errores aún devuelvan una respuesta válida, puede capturar esas excepciones de tipo WebExceptiony obtener el relacionado Response.

Dado que la respuesta a la excepción es de tipo System.Net.HttpWebResponse, mientras que la respuesta de una Invoke-WebRequestllamada exitosa es de tipo Microsoft.PowerShell.Commands.HtmlWebResponseObject, para devolver un tipo compatible de ambos escenarios necesitamos tomar la respuesta exitosa BaseResponse, que también es de tipo System.Net.HttpWebResponse.

El código de estado de este nuevo tipo de respuesta es una enumeración de tipo [system.net.httpstatuscode], en lugar de un entero simple, por lo que debe convertirlo explícitamente a int, o acceder a su Value__propiedad como se describe anteriormente para obtener el código numérico.

#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
fuente
5
Gracias, funcionó. No me di cuenta de que podía acceder al objeto Respuesta desde el objeto Excepción.
jcarpenter2
1
Sí, llegar al número de código real fue un poco complicado. :-)
Keith Hill
Mi opción
FoxDeploy
11
Una forma un poco mejor: $ response = try {Invoke-WebRequest localhost / foo } catch {$ _. Exception.Response} De esa forma obtendrá algo en la variable $ response en ambos casos. Pero tenga en cuenta que un error devuelve un HtmlWebResponse, pero un éxito devuelve un HtmlWebResponseObject. En particular, el StatusCode en esos son de diferentes tipos (suspiro ..)
Rob Cannon
4
Un par de ajustes menores a gran sugerencia de Rob, para evitar el problema con diferentes tipos: $response = try { (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseRequest } catch [System.Net.WebException] { $_.Exception.Response }. Es decir, la recuperación BaseRequestasegura que tanto en escenarios de éxito como de error obtenemos un HttpWebReqponse. Agregar [System.Net.WebException]asegura que solo capturamos excepciones relevantes de esta manera / no barremos accidentalmente otros tipos de problemas.
JohnLBevan
6

Dado que Powershell versión 7.0 Invoke-WebRequesttiene -SkipHttpErrorCheckparámetro de cambio.

-SkipHttpErrorCheck

Este parámetro hace que el cmdlet ignore los estados de error HTTP y continúe procesando respuestas. Las respuestas de error se escriben en la canalización como si tuvieran éxito.

Este parámetro se introdujo en PowerShell 7.

solicitud de extracción de documentos

Mariusz Pawelski
fuente
0

-SkipHttpErrorCheck es la mejor solución para PowerShell 7+, pero si aún no puede usarla, aquí tiene una alternativa simple que es útil para sesiones interactivas de Poweshell en la línea de comandos.

Cuando vea una descripción de error para una respuesta 404, es decir,

El servidor remoto devolvió un error: (404) No encontrado.

Luego puede ver el 'último error' desde la línea de comandos ingresando esto:

$Error[0].Exception.Response.StatusCode

O

$Error[0].Exception.Response.StatusDescription

O cualquier otra cosa que le gustaría saber del objeto "Respuesta".

DaveC
fuente