I have a Powershell script that uses System.Net.HttpWebRequest
to communicate with a remote host.
I create the request, set properties accordingly and call getresponse()
and getresponsestream()
to read the entire response from the server to a string. This works fine as long as the server responds with a "200 OK" message.
If the server responds with a "400 Bad Request" or any other error code, getresponse()
and getresponsestream()
throw exceptions and return nothing. My problem is there is more detailed error information included in the response header which I need so I can do my own error handling.
How would I be able to retrieve this 400 Bad Request signal?
Edit: I misunderstood the question at first, but it turns out that you can retrieve the response header by using the HttpWebResponse.GetResponseHeader()
method. If an exception occurs, the HttpWebRequest.GetResponse()
method returns $null
, and you have to use this code to retrieve the HttpWebResponse object, so that you can call GetResponseHeader()
on it:
# If an exception occurs, get the HttpWebResponse object from the WebException object
$HttpWebResponse = $Error[0].Exception.InnerException.Response;
I'm pretty sure you'll want to stick with the System.Net.HttpWebRequest
instead of the System.Net.WebClient
object. Here is an example, similar to what you probably already have:
# Create a HttpWebRequest using the Create() static method
$HttpWebRequest = [System.Net.HttpWebRequest]::Create("http://www.google.com/");
# Get an HttpWebResponse object
$HttpWebResponse = $HttpWebRequest.GetResponse();
# Get the integer value of the HttpStatusCode enumeration
Write-Host -Object $HttpWebResponse.StatusCode.value__;
The GetResponse() method returns a HttpWebResponse
object, which has a property named StatusCode
, which points to a value in the HttpStatusCode
.NET enumeration. Once you get a reference to the enumeration, we use the value__
property to get the integer that is associated with the returned enum value.
If you get a null value from the GetResponse()
method, then you'll want to read the most current error message in your catch {..} block. The Exception.ErrorRecord
property should be the most helpful.
try {
$HttpWebResponse = $null;
$HttpWebRequest = [System.Net.HttpWebRequest]::Create("http://www.asdf.com/asdf");
$HttpWebResponse = $HttpWebRequest.GetResponse();
if ($HttpWebResponse) {
Write-Host -Object $HttpWebResponse.StatusCode.value__;
Write-Host -Object $HttpWebResponse.GetResponseHeader("X-Detailed-Error");
}
}
catch {
$ErrorMessage = $Error[0].Exception.ErrorRecord.Exception.Message;
$Matched = ($ErrorMessage -match '[0-9]{3}')
if ($Matched) {
Write-Host -Object ('HTTP status code was {0} ({1})' -f $HttpStatusCode, $matches.0);
}
else {
Write-Host -Object $ErrorMessage;
}
$HttpWebResponse = $Error[0].Exception.InnerException.Response;
$HttpWebResponse.GetResponseHeader("X-Detailed-Error");
}
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx
http://msdn.microsoft.com/en-us/library/system.net.httpstatuscode.aspx
http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx
Ever tried the try and catch statements? This works fine for me.
ex:
$webclient = new-object system.net.webclient
try {
$domain = $webclient.downloadstring("http://xrsolis.com") # get a non existent domain
} catch {
write-host "domain inaccessible"
}