Httpclient on Android:Nohttpresponseexception Through Umts/3G

HttpClient on Android : NoHttpResponseException through UMTS/3G

I finally got rid of this problem : simply a HTTP header that was badly handled by a squid server on the road :

Expect: 100-Continue

It seems to be there by default with DefaultHttpClient on android SDK. To tackle this, simply add that in your code :

  HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);

HttpClient on Android : NoHttpResponseException through UMTS/3G

I finally got rid of this problem : simply a HTTP header that was badly handled by a squid server on the road :

Expect: 100-Continue

It seems to be there by default with DefaultHttpClient on android SDK. To tackle this, simply add that in your code :

  HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);

Android HttpGet throws NoHttpResponseException half the time?

turns out it was the server that was the problem. The way the server was setup it was not getting enough time to process the incoming request. The solution to the problem can be found in this link.

Spinneret web server fix

Android: org.apache.http.NoHttpResponseException: The target server failed to respond

I finally figured out what the problems is. When I do the Base64 encoding of the username and password, I use the wrong flag for Base64.encodeToString(...). So I change the falg:

FROM:

basicAuth = Base64.encodeToString(basicAuth.getBytes(), Base64.DEFAULT);

TO:

basicAuth = Base64.encodeToString(basicAuth.getBytes(), Base64.NO_WRAP);

... and everything is working just fine.

Https connection Android

We finally found the problem. It wasn't code related.

It was the reverse DNS that was timing-out. Because I dind't receive any answer from the reverse DNS my apache/ssl session was closed prematurely.

By using Google's DNS on a rooted device it worked.

The only thing left to do now is fix the our reverse DNS.

Here is a workaround : http://code.google.com/p/android/issues/detail?id=13117#c14

Call this method on your DefaultHttpClient or AndroidHttpClient instance. It will prevent the reverse DNS lookup from being made.

private void workAroundReverseDnsBugInHoneycombAndEarlier(HttpClient client) {
// Android had a bug where HTTPS made reverse DNS lookups (fixed in Ice Cream Sandwich)
// http://code.google.com/p/android/issues/detail?id=13117
SocketFactory socketFactory = new LayeredSocketFactory() {
SSLSocketFactory delegate = SSLSocketFactory.getSocketFactory();
@Override public Socket createSocket() throws IOException {
return delegate.createSocket();
}
@Override public Socket connectSocket(Socket sock, String host, int port,
InetAddress localAddress, int localPort, HttpParams params) throws IOException {
return delegate.connectSocket(sock, host, port, localAddress, localPort, params);
}
@Override public boolean isSecure(Socket sock) throws IllegalArgumentException {
return delegate.isSecure(sock);
}
@Override public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException {
injectHostname(socket, host);
return delegate.createSocket(socket, host, port, autoClose);
}
private void injectHostname(Socket socket, String host) {
try {
Field field = InetAddress.class.getDeclaredField("hostName");
field.setAccessible(true);
field.set(socket.getInetAddress(), host);
} catch (Exception ignored) {
}
}
};
client.getConnectionManager().getSchemeRegistry()
.register(new Scheme("https", socketFactory, 443));
}

Android Froyo: Connection to https using trusting all socket factory results in target server failed to respond

And now the issue was resolved.

The problem was not with the java / Android code but with the server configuration. The case was the following: I was trying to access the development environment server. However, it turned out our infrastructure engineer configured it with exactly the same certificate as the production server. This meant that the hostname in the certificate was erronous (matching the production environment).

Weird enough these web services were accessible through Firefox and Chrome, even with the wrong certificate, which caused all the confusion.

Hopefully describing my case here will help others in the future sort out the same problem.

duplicate requests from HttpClient

So what appears to be happening here is that your client sends a request, does not get a response in a timely manner, and as a result retries the same request again (as it should). This, in turn, results in multiple POST requests being sent to your server (almost in succession), which your server cannot currently deal with appropriately.

To verify/debug this, try disabling HTTP retries as follows:

defaultHttpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler
(0, false));

This of course will deal with your duplicate requests issue, but then introduces another more serious issue; namely, it will try once (and only once) and fail. From the information I got from your comments, here are a few ideas you can try:

Please bare with the pseudocode as I don't have all the details of how your client is architected

Handle Multiple POSTS in Succession

  • Disable automatic retries (as above)
  • Wrap your POST requests in a loop similar to how this is implemented
  • Then either sleep between your manual retries or implement your version of exponential backoff

No matter what, your server will need the capability to handle duplicate requests in a reasonable way, this is HTTP afterall. However, you're at least giving it a chance to process the first one before it's bombarded with duplicates.

I recommend that the first step it takes when processing a request is to set some form of a (duplicate) flag. Then if/when it receives a dupe, it continues processing the first request (as usual) and silently ignores the dupes.

So just to summarize, the point of this whole scheme was to give your server a chance to set the dupe flag. After that, it's your server's job to discard (or handle) duplicate requests as needed. Does this all make sense?



Related Topics



Leave a reply



Submit