Description
Hi,
today we spent quite a bit of time debugging a hang in the WebClient
in combination with using Apache's HttpComponentsClientHttpConnector
that essentially boils down to the following:
(I've put this also into an example under https://github.com/dreis2211/spring-httpclient-hang-demo for simpler reproduction)
@Test
@Timeout(value = 5)
void testWebClient() {
WebClient client = WebClient.builder().apply(customize()).build();
client.get()
.uri("/path")
.retrieve()
.bodyToMono(Void.class)
.block();
}
private Consumer<WebClient.Builder> customize() {
return builder -> {
ClientHttpConnector connector = buildClientConnector();
builder.clientConnector(connector);
builder.baseUrl(null); // Leads to invalid host
};
}
private ClientHttpConnector buildClientConnector() {
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom();
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(org.apache.hc.core5.util.Timeout.ofMilliseconds(1000))
.setResponseTimeout(org.apache.hc.core5.util.Timeout.ofMilliseconds(2000))
.build();
clientBuilder.setDefaultRequestConfig(config);
return new HttpComponentsClientHttpConnector(clientBuilder.build());
}
It seems that the empty or nulled baseUrl
should lead to an exception like the following, but the exception seems to be swallowed and the client request hangs afterwards.
Caused by: org.apache.hc.core5.http.ProtocolException: Target host is not specified
at org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner.determineRoute(DefaultRoutePlanner.java:65)
at org.apache.hc.client5.http.impl.async.InternalHttpAsyncClient.determineRoute(InternalHttpAsyncClient.java:113)
at org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$1.sendRequest(InternalAbstractHttpAsyncClient.java:195)
It might be very well a problem of Apache's HttpClient, but a quick look at https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java#L67 and commenting the line leads to the expected exception and no hang.
Unfortunately, my investigation time is limited and I hope you can take over from here.
The issue is obviously a misconfiguration of the WebClient in our particular case (and already fixed), but the hang is somewhat unexpected and dangerous. Especially if timeouts are configured one expects no infinite blocking.
Let me know if you need anything.
Cheers,
Christoph