Brian Mains
Brian Mains

Reputation: 50728

App to Web API Yields 400 Invalid Hostname

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.

Upvotes: 1

Views: 4001

Answers (3)

CallMeLaNN
CallMeLaNN

Reputation: 8568

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.

Upvotes: 5

ChrisLively
ChrisLively

Reputation: 88064

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.

Upvotes: 1

Szocske
Szocske

Reputation: 7661

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.

Upvotes: 1

Related Questions