Веб-запрос Powershell без исключения исключения на 4xx / 5xx

82

Я пишу сценарий PowerShell, который должен сделать веб-запрос и проверить код состояния ответа.

Я пробовал написать это:

$client = new-object system.net.webclient

$response = $client.DownloadData($url)

так же как и это:

$response = Invoke-WebRequest $url

но всякий раз, когда веб-страница имеет код состояния, который не является кодом состояния успеха, PowerShell выдает исключение вместо того, чтобы предоставить мне фактический объект ответа.

Как я могу получить код статуса страницы, даже если она не загружается?

jcarpenter2
источник
Это сработало для меня docs.microsoft.com/en-us/powershell/module/… Пример 7: Перехват сообщений об ошибках от Invoke-WebRequest
user3520245

Ответы:

121

Попробуй это:

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

Это своего рода облом, что это вызывает исключение, но так оно и есть.

Обновление по комментариям

Чтобы гарантировать, что такие ошибки по-прежнему возвращают действительный ответ, вы можете зафиксировать эти исключения типа WebExceptionи получить связанные Response.

Поскольку ответ на исключение имеет тип System.Net.HttpWebResponse, в то время как ответ на успешный Invoke-WebRequestвызов имеет тип Microsoft.PowerShell.Commands.HtmlWebResponseObject, для возврата совместимого типа из обоих сценариев нам нужно взять успешный ответ BaseResponse, который также имеет типSystem.Net.HttpWebResponse .

Код состояния этого нового типа ответа - это перечисление типа [system.net.httpstatuscode], а не простое целое число, поэтому вам нужно явно преобразовать его в int или получить доступ к его Value__свойству, как описано выше, чтобы получить числовой код.

#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__
Кейт Хилл
источник
5
Спасибо, сработало. Я не понимал, что вы можете просто получить доступ к объекту Response из объекта Exception.
jcarpenter2
1
Да, добраться до фактического номера кода было немного сложно. :-)
Кейт Хилл
Я использую этот код от Криса Вала, wahlnetwork.com/2015/02/19/…
FoxDeploy
11
Немного лучше: $ response = try {Invoke-WebRequest localhost / foo } catch {$ _. Exception.Response} Таким образом, вы получите что-то в переменной $ response в обоих случаях. Но имейте в виду, что в случае сбоя возвращается HtmlWebResponse, а в случае успеха возвращается HtmlWebResponseObject. В частности, StatusCode у них бывает разных типов (вздох ..)
Роб Кэннон
4
Несколько незначительных настроек с большим предложением Роба, чтобы избежать проблемы с различными типами: $response = try { (Invoke-WebRequest -Uri 'localhost/foo' -ErrorAction Stop).BaseRequest } catch [System.Net.WebException] { $_.Exception.Response }. Т.е. выборка BaseRequestгарантирует, что как в случае успеха, так и в случае ошибки мы получим файл HttpWebReqponse. Добавление [System.Net.WebException]гарантирует, что таким образом мы фиксируем только релевантные исключения / случайно не заметим другие типы проблем.
JohnLBevan 01
6

Поскольку Powershell версии 7.0 Invoke-WebRequestимеет -SkipHttpErrorCheckпараметр переключения.

-SkipHttpErrorCheck

Этот параметр заставляет командлет игнорировать статусы ошибок HTTP и продолжать обработку ответов. Ответы об ошибках записываются в конвейер так же, как если бы они были успешными.

Этот параметр был введен в PowerShell 7.

запрос на включение документов

Мариуш Павельски
источник
0

-SkipHttpErrorCheck - лучшее решение для PowerShell 7+, но если вы еще не можете его использовать, то вот простая альтернатива, которая полезна для интерактивных сеансов Poweshell в командной строке.

Когда вы видите описание ошибки для ответа 404, т. Е.

Удаленный сервер возвратил ошибку: (404) Не найдено.

Затем вы можете увидеть «последнюю ошибку» из командной строки, введя это:

$Error[0].Exception.Response.StatusCode

Или же

$Error[0].Exception.Response.StatusDescription

Или что-то еще, что вы хотели бы узнать об объекте Response.

Дэйв
источник