1

I have a strange problem. From my android app, I'm calling an ASP.NET Web API. I can make a POST request with no problem from the app. However, when I go to make a GET request, the request returns "400 bad request invalid hostname". This is strange as I can make a POST request, not a get. The URL I'm using is http://10.0.2.2/webapp/api/controllername (10.0.2.2 because android emulator uses 127.0.0.1; this is a published workaround). I do have the internet permission enabled.

I have the web API currently debugging, and I can debug the post requests. I can manually type in the URL in Internet Explorer for the get request, and hit the server. This is how I know it's working. I have a handler for application_beginrequest just to see that I am even hitting the server, and it is for the post requests. But I never even see a get request come in to the server.

To make the Android GET request, I utilized the following (added comments with additional information).

//Creation of get request
HttpGet request = new HttpGet(url); //correct URL; verified
for(NameValuePair h : headers)
{
    //6 headers added; verified OK
    request.addHeader(h.getName(), h.getValue());
}
//Calls method shown below
return executeRequest(request, url);

 private ResponseInformation executeRequest(HttpUriRequest request, String url) throws Exception
{
    HttpClient client = new DefaultHttpClient();
    HttpResponse httpResponse;

    try {
        //Get the response and check the code/message
        httpResponse = client.execute(request);
        responseCode = httpResponse.getStatusLine().getStatusCode();
        message = httpResponse.getStatusLine().getReasonPhrase();

        HttpEntity entity = httpResponse.getEntity();
        ResponseInformation info; // just a DTO for my needs

        if (entity != null) {
            InputStream instream = entity.getContent();
            //Response is an XML document listing the 400 error information
            response = convertStreamToString(instream);
            info = new ResponseInformation(responseCode, response, message);
            instream.close();
        }
        else
            info = new ResponseInformation(responseCode, message);

        return info;

    }
    .
    .
}

So I'm not sure who is doing the rejecting? Why would I get this error? It never hits Application_BeginRequest so it never makes it to my web API service, but POSTS do... so strange.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257

3 Answers3

5

I have the same issue by using Web API self host and can't send request either GET or POST.

The Web API produce 400 Invalid Hostname if the incoming host and Host header is not the same with the configured IIS or self-host hostname, see this. I use RawCap (WireShark can't monitor loopback IP in Windows) in my host and tcpdump inside Android emulator. The Host header somehow is automatically set to 10.0.2.2.

You can't see this issue by using Fiddler because you can get trough 127.0.0.1 without 10.0.2.2 workaround.

It will only happened if we use 10.0.2.2 special IP and the Http client library in Android application automatically set Host header to the IP. In my case, I use Retrofit. Since Host header 10.0.2.2 is not the same with either 127.0.0.1 or localhost, Web API Yields 400 Invalid Hostname.

Then I overwrite the Host header to localhost:port and it simply works:

RestAdapter.Builder builder= new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
     @Override
     public void intercept(RequestFacade request) {
         if (HOST.contains("10.0.2.2")) { // HOST = "http://10.0.2.2/api";
             request.addHeader("Host", "localhost");
         }            
     }
 });

Just make sure the Host header from your Android app is right.

CallMeLaNN
  • 8,328
  • 7
  • 59
  • 74
1

Try "wireshark" to capture the network traffic to see what is going wrong. Then try to emulate the HTTP request you see with wget or curl. That way you should be able to isolate what causes the service to fail.

Szocske
  • 7,466
  • 2
  • 20
  • 24
  • I can hit the service using fiddler with no problems. – Brian Mains Jan 05 '13 at 20:38
  • Good, then capture the failing one and see what the difference is. – Szocske Jan 06 '13 at 19:39
  • That's just it, it works from fiddler, but when the client is Android, it fails. However, I found out there was an alternative exception occurring. Maybe the 400 invalid hostname was masking it. I'm fixing that, and seeing if that makes the problem go away. Thanks. – Brian Mains Jan 07 '13 at 01:44
  • If you are using IIS server, make sure in the bindings for the website the IP set to default and "Host header value" set to an empty string. – Dmitry S. Jan 15 '13 at 06:32
  • 3
    there must be some difference between the two HTTP GET requests when looked at in a network analyzer other than the source IP address... Posting the two captured TCP flows may help us isolate the problem. – Szocske Jan 15 '13 at 14:00
  • @BrianMains You also need to capture the failing Android's request. Don't use the request builder. – maxbeaudoin Jan 18 '13 at 19:12
1

It is entirely possible that your get request is failing and is performing a redirect to a non existent error page. That redirect probably doesn't use the 10.0.2.2 ip address.

A common reason why you see it working directly (IE/Fiddler/Whatever) but not in your application is if the application isn't actually sending the exact same thing you are by alternative means.

The best bet is to simply have android either log or otherwise show you the exact query string it is trying to call. Then make sure your outside test is performing that call.

I would further investigate any type of standard error pages you might have, potentially turning them off until you can see the actual issue.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 10.0.2.2 is a workaround to the android emulator using up 127.0.0.1. Most have used this without issue. I can make a post request to that IP, but not a get. I'll take a look, but if I attach to the global.asax Application_BeginRequest, shouldn't I see some activity even if it was a redirect? I get no activity whatsoever, which leads me to believe it's Android. However, I copied this from a friend which has no issues with it. – Brian Mains Jan 16 '13 at 01:55
  • @BrianMains: If the request is garbled, IIS itself would handle the initial error and potential redirect which would never get down to the .net code. In other words, it's entirely possible android is sending the first request, IIS has not idea how handle so it doesn't hit your app and redirects to a non 10.0.2.2 address. – NotMe Jan 16 '13 at 17:06
  • Would that be logged by IIS? I did have Android show me the querystring, and it did look OK. I'll double check it to make sure. – Brian Mains Jan 16 '13 at 17:10
  • I can hit the service just fine from IE, using the URL copied from the address. It's so weird I can post, but not get request to the server from Android. – Brian Mains Jan 17 '13 at 04:38