In our web-application A user can submit a url. We will fetch the data and parse it server side. For each request we use an HttpClient with the following (relevant) settings
connectionManager.getParams().setConnectionTimeout(10000);
connectionManager.getParams().setSoTimeout(10000);
When I call HttpMethod.getResponseBody the status code has already been checked to be acceptable. At this point the thread hangs with this stack trace:
java.net.SocketInputStream.socketRead0 ( native code )
java.net.SocketInputStream.read ( SocketInputStream.java:150 )
java.net.SocketInputStream.read ( SocketInputStream.java:121 )
java.io.BufferedInputStream.read1 ( BufferedInputStream.java:273 )
java.io.BufferedInputStream.read ( BufferedInputStream.java:334 )
java.io.FilterInputStream.read ( FilterInputStream.java:133 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:108 )
java.io.FilterInputStream.read ( FilterInputStream.java:107 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:127 )
org.apache.commons.httpclient.HttpMethodBase.getResponseBody ( HttpMethodBase.java:690 )
I cannot discover the exact URL for which this happened (was an incident on a live environment) and I have been unable to reproduce it. I'd like to think it's simply a matter of the server we're connecting to behaving strangely, but perhaps I'm missing something. In either case, is there a way for me to prevent the blocking method call from waiting forever? The SoTimeout is also the socket read timeout? Is there another setting I'm missing?
I have all the timeouts setup just fine but I found out we have on url that does http chunking but sends no results(works fine in chrome, but in http client it hangs forever even with the timeout set). Luckily I own the server and just return some garbage and it no longer hangs. This seems like a very unique bug in that http client does not handle some kind of empty chunking case well(though I could be way off)....I just know it hangs every time on that same url with empty data and that url is http chunking csv download back to our http client.
When I call HttpMethod.getResponseBody the status code has already been checked to be acceptable. At this point the thread hangs
Looks like you have a problem with synchronizing the calls ... you should ensure that the method
HttpMethod.getResponseBody
is called sequentially or should use a mutex (semaphore ) for the part that changes the status code
Also you should decrease your timeout limit to prevent hangs.
We see this consistently in our implementation and it looks like http client is not handling bad servers correctly or something and it is not timing out.....I can reproduce in our setting with this databus open source project and the stack trace is a little different...
SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int) line: not available [native method]
SocketInputStream.read(byte[], int, int) line: 129
SocketInputBuffer(AbstractSessionInputBuffer).fillBuffer() line: 166
SocketInputBuffer.fillBuffer() line: 90
SocketInputBuffer(AbstractSessionInputBuffer).readLine(CharArrayBuffer) line: 281
DefaultHttpResponseParser.parseHead(SessionInputBuffer) line: 92
DefaultHttpResponseParser.parseHead(SessionInputBuffer) line: 62
DefaultHttpResponseParser(AbstractMessageParser).parse() line: 254
DefaultClientConnection(AbstractHttpClientConnection).receiveResponseHeader() line: 289
DefaultClientConnection.receiveResponseHeader() line: 252
BasicPooledConnAdapter(AbstractClientConnAdapter).receiveResponseHeader() line: 219
HttpRequestExecutor.doReceiveResponse(HttpRequest, HttpClientConnection, HttpContext) line: 300
HttpRequestExecutor.execute(HttpRequest, HttpClientConnection, HttpContext) line: 127
DefaultRequestDirector.tryExecute(RoutedRequest, HttpContext) line: 712
DefaultRequestDirector.execute(HttpHost, HttpRequest, HttpContext) line: 517
DefaultHttpClient(AbstractHttpClient).execute(HttpHost, HttpRequest, HttpContext) line: 906
DefaultHttpClient(AbstractHttpClient).execute(HttpUriRequest, HttpContext) line: 805
ReadAggregations.processAggregation(String, Counter, Counter, Counter, Counter) line: 153
ReadAggregations.start() line: 96
ReadAggregations.main(String[]) line: 70
You can try to abort the request with HttpUriRequest#abort(), see https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/methods/HttpUriRequest.html#abort%28%29. However, setting a timemout that requires no intercepting would be nicer.
Here is a related question: Setting time out in apache http client
HttpClient distinguishes between connection and request. setSoTimeout
will configure the connection socket timeout while setConnectionTimeout
will configure both the timeout for the connection manager (how long to wait for a connection) and for the establishment of the connection itself. In the code you provided, you are not setting any timeout for the socket used for the request itself, and unfortunately, HttpClient has no timeout by default for that.
Here's how I do it in v4.4.1:
// Configure the socket timeout for the connection, incl. ssl tunneling
connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(100);
SocketConfig sc = SocketConfig.custom()
.setSoTimeout(soTimeoutMs)
.build();
connManager.setDefaultSocketConfig(sc);
HttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.setConnectionManagerShared(true)
.build();
// configure the timeouts (socket and connection) for the request
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT);
config.setConnectionRequestTimeout(connectionTimeoutMs);
config.setSocketTimeout(socketTimeoutMs);
HttpRequestBase req = new HttpGet(uri);
req.setConfig(config.build());
client.execute(req);