在4xx/5xx 上不抛出异常的 Powershell web 请求

我正在编写一个 Powershell 脚本,它需要发出一个 web 请求并检查响应的状态代码。

我试过这样写:

$client = new-object system.net.webclient


$response = $client.DownloadData($url)

还有这个:

$response = Invoke-WebRequest $url

但是,只要网页的状态代码不是成功状态代码,PowerShell 就会抛出一个异常,而不是给我实际的响应对象。

即使页面加载失败,我怎样才能得到它的状态代码?

87124 次浏览

Try this:

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

It is kind of a bummer that this throws an exception but that's the way it is.

Update per comments

To ensure that such errors still return a valid response, you can capture those exceptions of type WebException and fetch the related Response.

Since the response on the exception is of type System.Net.HttpWebResponse, whilst the response from a successful Invoke-WebRequest call is of type Microsoft.PowerShell.Commands.HtmlWebResponseObject, to return a compatible type from both scenarios we need to take the successful response's BaseResponse, which is also of type System.Net.HttpWebResponse.

This new response type's status code an enum of type [system.net.httpstatuscode], rather than a simple integer, so you have to explicity convert it to int, or access it's Value__ property as described above to get the numeric code.

#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__

Since Powershell version 7.0 Invoke-WebRequest have -SkipHttpErrorCheck switch parameter.

-SkipHttpErrorCheck

This parameter causes the cmdlet to ignore HTTP error statuses and continue to process responses. The error responses are written to the pipeline just as if they were successful.

This parameter was introduced in PowerShell 7.

docs pull request

-SkipHttpErrorCheck is the best solution for PowerShell 7+, but if you can't use that yet then here is a simple alternative that is useful for interactive, command-line Poweshell sessions.

When you see the an error description for a 404 response, i.e.,

The remote server returned an error: (404) Not Found.

Then you can see the 'last error' from the command-line by entering this:

$Error[0].Exception.Response.StatusCode

Or

$Error[0].Exception.Response.StatusDescription

Or whatever else you would like to know from the `Response’ object.