-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
Brian Clozel opened SPR-15920 and commented
Problems with the WebClient API
Given the current WebClient
API, it is possible to have:
Mono<String> result = this.webClient.get()
.uri("/greeting")
.retrieve()
.bodyToMono(String.class);
In that case, we're consuming the response body completely; under the covers, reactor-netty will dispose the connection (close it or return it to the connection pool) as soon as the body has been consumed.
But we can also do this:
Mono<HttpStatus> status = this.webClient.get()
.uri("/example")
.exchange()
.map(response -> response.statusCode());
In that case, the body is not consumed, and the underlying client has no way of knowing that the connection should be closed. This can lead to issues with the connection pool, memory leaks, etc.
In the ClientConnector#connect
method, before returning the ClientHttpResponse
, we could do something like:
responseMono.doOnTerminate((response, ex) -> {
if (response != null) {
response.dispose();
}
})
But unfortunately, this will close the connection too soon. The first example can be rewritten like:
Mono<ResponseEntity<String>> result = this.webClient.get()
.uri("/greeting")
.exchange()
.flatMap(response -> response.toEntity(String.class));
With the flatMap
operator, we wait until the Mono<ClientHttpResponse>
is completed and proceed with the body. The completion triggers that doOnTerminate
operator.
Reactor Netty changes
Reactor Netty is currently dealing with this in its API and considering the following changes:
public interface ResponseReceiver {
// HttpClientResponse has no reference to the body, just headers/status/etc
Mono<HttpClientResponse> response();
<V> Flux<V> response(BiFunction<? super HttpClientResponse, ? super ByteBufFlux, ? extends Publisher<? extends V>> receiver);
ByteBufFlux responseContent();
<V> Mono<V> responseSingle(BiFunction<? super HttpClientResponse, ? super ByteBufMono, ? extends Mono<? extends V>> receiver);
}
With this type of changes, the response body Publisher
is tied back to the lifecycle of the connection.
We need to revisit our current client API to make sure that the connection lifecycle can be properly managed for the underlying client library.
Issue Links:
- Allow Consumer-style access to FluxExchangeResult within chain of calls [SPR-15959] #20511 Allow Consumer-style access to FluxExchangeResult within chain of calls
- Revisit how WebClient disposes connection [SPR-15993] #20542 Revisit how WebClient disposes connection