20

We want to migrate all our apache-httpclient-4.x code to java-http-client code to reduce dependencies. While migrating them, I ran into the following issue under Java 11:

How to set the socket timeout in Java HTTP Client?

With apache-httpclient-4.x we can set the connection timeout and the socket timeout like this:

DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);

With java-http-client I can only set the connection timeout like this:

HttpClient httpClient = HttpClient.newBuilder()
                                  .connectTimeout(Duration.ofSeconds(5))
                                  .build()

But I found no way to set the socket timeout. Is there any way or an open issue to support that in the future?

0

2 Answers 2

21

You can specify it at the HttpRequest.Builder level via the timeout method:

HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(5))
                .build();

HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create("..."))
                .timeout(Duration.ofSeconds(5)) //this
                .build();


httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

If you've got connected successfully but not able to receive a response at the desired amount of time, java.net.http.HttpTimeoutException: request timed out will be thrown (in contrast with java.net.http.HttpConnectTimeoutException: HTTP connect timed out which will be thrown if you don't get a successful connection).

Sign up to request clarification or add additional context in comments.

2 Comments

This method is at the HttpRequest.Builder level, not the HttpRequest level. Amended your post accordingly.
This isn't exactly a socket timeout; this is more like a timeout from when the request is sent until the headers are received. The response could end up taking much longer and even if 5 seconds go by between receiving data it will not trigger this timeout.
2

There doesn't seem to be a way to specify a timeout on the flow of packets (socket timeout) on the Java Http Client.

I found an enhancement request on OpenJDK which seems to cover this possibility - https://bugs.openjdk.org/browse/JDK-8258397

Content from the link

The HttpClient lets you set a connection timeout (HttpClient.Builder) and a request timeout (HttpRequest.Builder). However the request timeout will be cancelled as soon as the response headers have been read. There is currently no timeout covering the reception of the body.

A possibility for the caller is to make use of the CompletableFuture API (get/join will accept a timeout, or CF::orTimeout can be called). IIRC - in that case, it will still be the responsibility of the caller to cancel the request. We might want to reexamine and possibility change that. The disadvantage here is that some of our BodyHandlers (ofPublisher, ofInputStream) will return immediately - so the CF API won't help in this case. This might be a good thing (or not).

Another possibility could be to add a body timeout on HttpRequest.Builder. This would then cover all cases - but do we really want to timeout in the case of ofInputStream or ofPublisher if the caller doesn't read the body fast enough?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.