Ensure client response is drained with onStatus hook
Issue: SPR-17473
This commit is contained in:
@@ -433,12 +433,22 @@ class DefaultWebClient implements WebClient {
|
||||
private <T extends Publisher<?>> T bodyToPublisher(ClientResponse response,
|
||||
T bodyPublisher, Function<Mono<? extends Throwable>, T> errorFunction) {
|
||||
|
||||
return this.statusHandlers.stream()
|
||||
.filter(statusHandler -> statusHandler.test(response.statusCode()))
|
||||
.findFirst()
|
||||
.map(statusHandler -> statusHandler.apply(response))
|
||||
.map(errorFunction::apply)
|
||||
.orElse(bodyPublisher);
|
||||
for (StatusHandler handler : this.statusHandlers) {
|
||||
if (handler.test(response.statusCode())) {
|
||||
Mono<? extends Throwable> exMono = handler.apply(response);
|
||||
exMono = exMono.flatMap(ex -> drainBody(response, ex));
|
||||
exMono = exMono.onErrorResume(ex -> drainBody(response, ex));
|
||||
return errorFunction.apply(exMono);
|
||||
}
|
||||
}
|
||||
return bodyPublisher;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Mono<T> drainBody(ClientResponse response, Throwable ex) {
|
||||
// Ensure the body is drained, even if the StatusHandler didn't consume it,
|
||||
// but ignore errors in case it did consume it.
|
||||
return (Mono<T>) response.bodyToMono(Void.class).onErrorMap(ex2 -> ex).thenReturn(ex);
|
||||
}
|
||||
|
||||
private static Mono<WebClientResponseException> createResponseException(ClientResponse response) {
|
||||
|
||||
@@ -596,6 +596,9 @@ public interface WebClient {
|
||||
* {@link WebClientResponseException} when the response status code is 4xx or 5xx.
|
||||
* @param statusPredicate a predicate that indicates whether {@code exceptionFunction}
|
||||
* applies
|
||||
* <p><strong>NOTE:</strong> if the response is expected to have content,
|
||||
* the exceptionFunction should consume it. If not, the content will be
|
||||
* automatically drained to ensure resources are released.
|
||||
* @param exceptionFunction the function that returns the exception
|
||||
* @return this builder
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user