none
System.Net.WebRequest :: "The remote server returned an error: (400) Bad Request."

    Question

  • Alright, so I've gotten the list of servers, that I want to test. I parse them out to a URI and I hit that URI with a WebRequest and I receive the aforementioned error.

    Ze code:

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $request = foreach($i in $End_url) {[System.Net.WebRequest]::Create($i)}
    $response = foreach($i in $request) {$i.GetResponse()}
    $status = foreach($i in $response) {$i.StatusDescription}
    


    Unfortunately, I'm unsure why I'm sending a bad-request. I just want to do a "GET", as it were, and get the response "OK". (I have a clause for it's not OK). Anyways, I was told I might be using the wrong method/command, as I would have to send something to the server in the form of a header. I thought that the WebRequest would work for something, such as this (i.e.: construct the http-get header).

    I've taken everything out of the functions that I have, and can - emphatically - say that the request (or the request for the response) is what is breaking the script. How do I know which part (WebRequest or GetResponse) is breaking and if it's the GetResponse, how do I "fix" it?

    Monday, February 06, 2012 2:03 PM

Answers

  • I found my answer: I had to construct headers, to construct the expected and correct request.

    $mthHDR.Headers.Add("HTTP-HOST", "<hostname>")
    $mthHDR.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”

    Also, it was pointed out to me that, instead of using an interation from a collection to the main code, it would be much more efficient and less resource intensive to get the collection and then do a foreach.

    Before:

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $request = foreach($i in $End_url) {[System.Net.WebRequest]::Create($i)}
    $response = foreach($i in $request) {$i.GetResponse()}
    $status = foreach($i in $response) {$i.StatusDescription}

    After:

    foreach($server in $colServer) 
    {
    	$strURI = "https://" + $server.fqdn + "/url/"
    	$mthHDR = [System.Net.WebRequest]::Create("$strURI")
    	$mthHDR.Headers.Add("HTTP-HOST", "<hostname>")
    	$mthHDR.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”
    	#we prompt for the response
    	$mthRSP = $mthHDR.GetResponse()
    	$mthSTAT = $mthRSP.StatusDescription
    }

    Hope this helps someone, if they ever run into this problem.
    Monday, February 13, 2012 3:54 AM

All replies

  • What are you testing against?  Regular web page?  Web service?  WCF?
    Tuesday, February 07, 2012 12:22 AM
  • Any webpage hosted from IIS.
    Tuesday, February 07, 2012 9:54 AM
  • FWIW, I tried this against my local IIS instance, and got an OK response.  Have you tried your code against a single URI?

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $request = [System.Net.WebRequest]::Create('http://localhost')
    $response = $request.GetResponse()
    $status = $response.StatusDescription
    Write-Host $status


    Grant Ward, a.k.a. Bigteddy

    What's new in Powershell 3.0 (Technet Wiki)

    Network Live Audit - Powershell script

    Tuesday, February 07, 2012 1:22 PM
  •  
    you could probably just slap the service point code in there and be good to
    go.
     
     

    Justin Rich
    http://jrich523.wordpress.com
    PowerShell V3 Guide (Technet)
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Tuesday, February 07, 2012 1:24 PM
  • did you test the URI in IE/Firefox? maybe the URI is bad. A 400 return says
    you are getting to the server perhaps the URI you are using isnt what you
    think it is.
     
     

    Justin Rich
    http://jrich523.wordpress.com
    PowerShell V3 Guide (Technet)
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Tuesday, February 07, 2012 1:26 PM
  • I'm building the URI by getting a list of servers, appending "https://" + $servername + "url".

    I've verified that the URI parsing is working, by taking each line of code out of the functions and doing them individually in Powershell.

    Basically, I'm trying to do a "get" and trying to obtain the 100-OK, as a test against multiple servers; in either https or http. I don't want to use the hostname, itself, because as long as 443 is open, I believe I'll always get an 'OK' response, even if IIS is in a stopped state; thus, the need/want to parse the URI - that and it makes it portable/moldable against any site within or outside the org.

    Here's the whole code-block:

    Add-Type –AssemblyName System
    Add-Type -AssemblyName System.Management.Automation
    Add-Type –AssemblyName System.Net
    
    function Servers
    {
    	$Boxez = Get-Content Serverz.txt
    	$Raw_url = foreach($i in $Boxez) {"https://" + ($i)}
    	$End_url = foreach($i in $Raw_url){$i + "/url/"}
    	IIS_Test
    }
    
    function IIS_Test
    {
    		[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    		$request = foreach($i in $End_url) {[System.Net.WebRequest]::Create($i)}
    		$response = foreach($i in $request) {$i.GetResponse()}
    		$status = foreach($i in $response) {$i.StatusDescription}
    		If($status -like "*OK*")
    		{
    			Write-Host -ForeGroundColor Green "The test passed."
    		}
    		else
    		{
    			Write-Host -ForeGroundColor Red "The test has failed."
    		}
    }
    
    Servers

    Tuesday, February 07, 2012 1:50 PM
  • Do you get the same response when you test against 'https://localhost'? That's what I'm using.

    Tuesday, February 07, 2012 2:08 PM
  • you don’t pass $I in to your function, id create this as the function
     
    function Test-HTTPPage
    {
    param([string] $URI)
           [System.Net.ServicePointManager]::ServerCertificateValidationCallback
    = {$true}
           $request = [System.Net.WebRequest]::Create($URI)
           try{
           $response = $request.GetResponse()
           write-host "Success"
           }
           catch{
           write-host "Failed: $($_.exception.innerexception.message)"
           }
    }
     
    then pass the URIs to it. Also I'd probably remove the "write-host" but it
    depends on what you are doing. typically you want to pass back an object,
    like this
     
    function Test-HTTPPage
    {
    param([string] $URI)
           $rtn = ""|select URI,Return
           $rtn.URI = $uri
           [System.Net.ServicePointManager]::ServerCertificateValidationCallback
    = {$true}
           $request = [System.Net.WebRequest]::Create($URI)
           try{
           $response = $request.GetResponse()
           $rtn.return = "Success"
           }
           catch{
           $rtn.return =  "Failed: $($_.exception.innerexception.message)"
           }
           $rtn
    }
     
     

    Justin Rich
    http://jrich523.wordpress.com
    PowerShell V3 Guide (Technet)
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Tuesday, February 07, 2012 2:14 PM
  • Same segment? Proxies? Anything other than a plain http connection?  When I run a simplified version of your script (bypassing all the iterators) I get this:

    PS > $End_Url = "http://www.google.com"
    PS > [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    PS > $request = foreach($i in $End_url) {[System.Net.WebRequest]::Create($i)}
    PS > $response = foreach($i in $request) {$i.GetResponse()}
    PS > $status = foreach($i in $response) {$i.StatusDescription}
    PS > $status
    OK
    PS > $i
    IsMutuallyAuthenticated : False
    Cookies                 : {}
    Headers                 : {Cache-Control, Content-Type, Date, Expires...}
    ContentLength           : -1
    ContentEncoding         :
    ContentType             : text/html; charset=ISO-8859-1
    CharacterSet            : ISO-8859-1
    Server                  : gws
    LastModified            : 2/7/2012 8:00:00 AM
    StatusCode              : OK
    StatusDescription       : OK
    ProtocolVersion         : 1.1
    ResponseUri             : https://www.google.com/
    Method                  : GET
    IsFromCache             : False
    

    While tracking the request with Wireshark I see the headers ($i.Headers.AllKeys()) pass in my monitor directly within the http stream but am unable to access their values in the response passed back from GetResponse().

    Tuesday, February 07, 2012 2:30 PM
  • I found my answer: I had to construct headers, to construct the expected and correct request.

    $mthHDR.Headers.Add("HTTP-HOST", "<hostname>")
    $mthHDR.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”

    Also, it was pointed out to me that, instead of using an interation from a collection to the main code, it would be much more efficient and less resource intensive to get the collection and then do a foreach.

    Before:

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $request = foreach($i in $End_url) {[System.Net.WebRequest]::Create($i)}
    $response = foreach($i in $request) {$i.GetResponse()}
    $status = foreach($i in $response) {$i.StatusDescription}

    After:

    foreach($server in $colServer) 
    {
    	$strURI = "https://" + $server.fqdn + "/url/"
    	$mthHDR = [System.Net.WebRequest]::Create("$strURI")
    	$mthHDR.Headers.Add("HTTP-HOST", "<hostname>")
    	$mthHDR.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)”
    	#we prompt for the response
    	$mthRSP = $mthHDR.GetResponse()
    	$mthSTAT = $mthRSP.StatusDescription
    }

    Hope this helps someone, if they ever run into this problem.
    Monday, February 13, 2012 3:54 AM
  • this works pretty cool until you get a certificate error then the GetResponse comes back with the following error:

    Exception calling "GetResponse" with "0" argument(s): "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
    At line:1 char:34
    +     $mthRSP = $mthHDR.GetResponse <<<< ()
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

    My question is: how can I tell the server to ignore the SSL error and continue with the get command like when get the error on a browser giving you the option to continue with the session or not...?

    LCR


    • Edited by itlcr Monday, August 27, 2012 1:55 PM
    Monday, August 27, 2012 1:53 PM