How should I deal with servers that hang sending an HTTP response body using the HTTP client included in Java 11 onwards, when I need to handle the response in a streaming fashion?
Having read the documentation, I'm aware that it's possible to set a timeout on connection and a timeout on the request:
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(2))
.build();
HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://example.com"))
.timeout(Duration.ofSeconds(5))
.build();
HttpResponse<Stream<String>> httpResponse = httpClient
.send(httpRequest, HttpResponse.BodyHandlers.ofLines());
Stream<String> responseLineStream = httpResponse.body();
responseLineStream.count();
In the above code:
- If a connection cannot be established within 2 seconds, a timeout exception will be thrown.
- If a response is not received within 5 seconds, a timeout exception will be thrown. By experimentation, the timer starts after the connection is established, and for this type of
BodyHandler, a response is considered received when the status line and headers have been received.
This means that when the code executes, within 7 seconds either an exception will have been thrown, or we'll have arrived at the last line. However, the last line isn't constrained by any timeout. If the server stops sending the response body, the last line blocks forever.
How can I prevent the last line hanging in this case?