Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 444
CarllDev Avatar asked Jul 31 '14 11:07

CarllDev


People also ask

Can 404 return body?

It is very common for 404 responses to contain content in the body. The first example would be when you go to web sites, you get a helpful HTML page that has links to go back or go to the front page. There is no reason why an API call shouldn't return a response body.

Why do I keep getting a 404 error on google?

As you might know, a 404 error is "File not found." This can happen when a file is deleted or there is an error in a hyperlink. It can also happen if a file is copied and the original deleted. The new file will have a new address and previous links will not work.


2 Answers

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
}
like image 54
BrokenGlass Avatar answered Sep 20 '22 18:09

BrokenGlass


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() )

like image 37
Paul Fijma Avatar answered Sep 18 '22 18:09

Paul Fijma