How do you get the response from a 404 page requested from powershell

13,200

Solution 1

Change your catch clause to catch the more specific WebException, then you can use the Response property on it to get the status code:

{
  #...
} 
catch [System.Net.WebException] 
{
    $statusCode = [int]$_.Exception.Response.StatusCode
    $html = $_.Exception.Response.StatusDescription
}

Solution 2

BrokenGlass gave the answer, but this might help:

try
{
  $URI='http://8bit-museum.de/notfound.htm'
  $HTTP_Request = [System.Net.WebRequest]::Create($URI)
  "check: $URI"
  $HTTP_Response = $HTTP_Request.GetResponse()
  # We then get the HTTP code as an integer.
  $HTTP_Status = [int]$HTTP_Response.StatusCode
} 
catch [System.Net.WebException] 
{
    $statusCode = [int]$_.Exception.Response.StatusCode
    $statusCode
    $html = $_.Exception.Response.StatusDescription
    $html
}
$HTTP_Response.Close()

Response: check: http://8bit-museum.de/notfound.htm 404 Not Found

another approach:

$URI='http://8bit-museum.de/notfound.htm'
try {
  $HttpWebResponse = $null;
  $HttpWebRequest = [System.Net.HttpWebRequest]::Create("$URI");
  $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");
}

if i understand the question then $ErrorMessage = $Error[0].Exception.ErrorRecord.Exception.Message contains the errormessage you are looking for. (source: Error Handling in System.Net.HttpWebRequest::GetResponse() )

Share:
13,200
CarllDev
Author by

CarllDev

I'm a developer living, working and playing in London. My day-job focuses on C# development but I do the odd project at home in Android and have recently done a project using GAE and Python. Other skills/abilities include: * Microsoft SQL Server * Python (newly added - beginner) * GAE Datastore (newly added - beginner) I love playing with new technologies.

Updated on June 18, 2022

Comments

  • CarllDev
    CarllDev over 1 year

    I have to call an API exposed by TeamCity that will tell me whether a user exists. The API url is this: http://myteamcityserver.com:8080/httpAuth/app/rest/users/monkey

    When called from the browser (or fiddler), I get the following back:

    Error has occurred during request processing (Not Found).
    Error: jetbrains.buildServer.server.rest.errors.NotFoundException: No user can be found by username 'monkey'.
    Could not find the entity requested. Check the reference is correct and the user has permissions to access the entity.
    

    I have to call the API using powershell. When I do it I get an exception and I don't see the text above. This is the powershell I use:

    try{
        $client = New-Object System.Net.WebClient
        $client.Credentials = New-Object System.Net.NetworkCredential $TeamCityAgentUserName, $TeamCityAgentPassword
        $teamCityUser = $client.DownloadString($url)
        return $teamCityUser
    }
    catch
    {
        $exceptionDetails = $_.Exception
        Write-Host "$exceptionDetails" -foregroundcolor "red"
    }
    

    The exception:

    System.Management.Automation.MethodInvocationException: Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (404) Not Found." ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
       at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
       at System.Net.WebClient.DownloadString(Uri address)
       at CallSite.Target(Closure , CallSite , Object , Object )
       --- End of inner exception stack trace ---
       at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
       at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
       at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
    

    I need to be able to check that the page is returned contains the text described above. This way I know whether I should create a new user automatically or not. I could just check for 404, but my fear is that if the API is changed and the call really returns a 404, then I would be none the wiser.

  • BrokenGlass
    BrokenGlass over 9 years
    launching IE just for doing a web request sounds like a really bad idea
  • CarllDev
    CarllDev over 9 years
    I tried this, and though it gives a nice status code, it still doesn't give me the "Could not find the entity requested" text that I'm looking for. Thanks though.
  • BrokenGlass
    BrokenGlass over 9 years
    This is the correct way to get the status code - to get the html response itself you will have to parse the response stream - e.g. see stackoverflow.com/questions/7036491/… for an example in C# that you can easily adapt to Powershell
  • CarllDev
    CarllDev over 9 years
    Having read the stackoverflow post you pointed me at, I have come to the following code which is exactly what I need: catch [System.Net.WebException] { $exception = $_.Exception $respstream = $exception.Response.GetResponseStream() $sr = new-object System.IO.StreamReader $respstream $result = $sr.ReadToEnd() write-host $result }
  • trebleCode
    trebleCode over 5 years
    100% agree with @BrokenGlass