Optimize WebClientUtils
Use constant Predicate for exception wrapping. Use ResponseEntity constructor instead of builder. See gh-26069
This commit is contained in:
parent
5338d8b5e9
commit
ba9325446c
|
|
@ -113,9 +113,18 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
|||
* @param status the status code
|
||||
*/
|
||||
public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
|
||||
super(body, headers);
|
||||
Assert.notNull(status, "HttpStatus must not be null");
|
||||
this.status = status;
|
||||
this(body, headers, (Object) status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code HttpEntity} with the given body, headers, and status code.
|
||||
* @param body the entity body
|
||||
* @param headers the entity headers
|
||||
* @param rawStatus the status code value
|
||||
* @since 5.3.2
|
||||
*/
|
||||
public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, int rawStatus) {
|
||||
this(body, headers, (Object) rawStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -543,16 +543,10 @@ class DefaultWebClient implements WebClient {
|
|||
return this.responseMono.flatMap(response -> handleBodyMono(response, response.bodyToMono(elementTypeRef)));
|
||||
}
|
||||
|
||||
private <T> Mono<T> handleBodyMono(ClientResponse response, Mono<T> bodyPublisher) {
|
||||
private <T> Mono<T> handleBodyMono(ClientResponse response, Mono<T> body) {
|
||||
body = body.onErrorResume(WebClientUtils.WRAP_EXCEPTION_PREDICATE, exceptionWrappingFunction(response));
|
||||
Mono<T> result = statusHandlers(response);
|
||||
Mono<T> wrappedExceptions = bodyPublisher.onErrorResume(WebClientUtils::shouldWrapException,
|
||||
t -> wrapException(t, response));
|
||||
if (result != null) {
|
||||
return result.switchIfEmpty(wrappedExceptions);
|
||||
}
|
||||
else {
|
||||
return wrappedExceptions;
|
||||
}
|
||||
return (result != null ? result.switchIfEmpty(body) : body);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -567,16 +561,10 @@ class DefaultWebClient implements WebClient {
|
|||
return this.responseMono.flatMapMany(response -> handleBodyFlux(response, response.bodyToFlux(elementTypeRef)));
|
||||
}
|
||||
|
||||
private <T> Publisher<T> handleBodyFlux(ClientResponse response, Flux<T> bodyPublisher) {
|
||||
private <T> Publisher<T> handleBodyFlux(ClientResponse response, Flux<T> body) {
|
||||
body = body.onErrorResume(WebClientUtils.WRAP_EXCEPTION_PREDICATE, exceptionWrappingFunction(response));
|
||||
Mono<T> result = statusHandlers(response);
|
||||
Flux<T> wrappedExceptions = bodyPublisher.onErrorResume(WebClientUtils::shouldWrapException,
|
||||
t -> wrapException(t, response));
|
||||
if (result != null) {
|
||||
return result.flux().switchIfEmpty(wrappedExceptions);
|
||||
}
|
||||
else {
|
||||
return wrappedExceptions;
|
||||
}
|
||||
return (result != null ? result.flux().switchIfEmpty(body) : body);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
@ -608,10 +596,8 @@ class DefaultWebClient implements WebClient {
|
|||
return result.checkpoint(description);
|
||||
}
|
||||
|
||||
private <T> Mono<T> wrapException(Throwable throwable, ClientResponse response) {
|
||||
return response.createException()
|
||||
.map(responseException -> responseException.initCause(throwable))
|
||||
.flatMap(Mono::error);
|
||||
private <T> Function<Throwable, Mono<? extends T>> exceptionWrappingFunction(ClientResponse response) {
|
||||
return t -> response.createException().flatMap(ex -> Mono.error(ex.initCause(t)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ public abstract class ExchangeFunctions {
|
|||
.connect(httpMethod, url, httpRequest -> clientRequest.writeTo(httpRequest, this.strategies))
|
||||
.doOnRequest(n -> logRequest(clientRequest))
|
||||
.doOnCancel(() -> logger.debug(logPrefix + "Cancel signal (to close connection)"))
|
||||
.onErrorResume(WebClientUtils::shouldWrapException, t -> wrapException(t, clientRequest))
|
||||
.onErrorResume(WebClientUtils.WRAP_EXCEPTION_PREDICATE, t -> wrapException(t, clientRequest))
|
||||
.map(httpResponse -> {
|
||||
logResponse(httpResponse, logPrefix);
|
||||
return new DefaultClientResponse(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.reactive.function.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
|
@ -26,7 +27,8 @@ import org.springframework.core.codec.CodecException;
|
|||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* Internal methods shared between {@link DefaultWebClient} and {@link DefaultClientResponse}.
|
||||
* Internal methods shared between {@link DefaultWebClient} and
|
||||
* {@link DefaultClientResponse}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.2
|
||||
|
|
@ -35,6 +37,12 @@ abstract class WebClientUtils {
|
|||
|
||||
private static final String VALUE_NONE = "\n\t\t\n\t\t\n\uE000\uE001\uE002\n\t\t\t\t\n";
|
||||
|
||||
/**
|
||||
* Predicate that returns true if an exception should be wrapped.
|
||||
*/
|
||||
public final static Predicate<? super Throwable> WRAP_EXCEPTION_PREDICATE =
|
||||
t -> !(t instanceof WebClientException) && !(t instanceof CodecException);
|
||||
|
||||
|
||||
/**
|
||||
* Map the given response to a single value {@code ResponseEntity<T>}.
|
||||
|
|
@ -42,9 +50,10 @@ abstract class WebClientUtils {
|
|||
@SuppressWarnings("unchecked")
|
||||
public static <T> Mono<ResponseEntity<T>> mapToEntity(ClientResponse response, Mono<T> bodyMono) {
|
||||
return ((Mono<Object>) bodyMono).defaultIfEmpty(VALUE_NONE).map(body ->
|
||||
ResponseEntity.status(response.rawStatusCode())
|
||||
.headers(response.headers().asHttpHeaders())
|
||||
.body(body != VALUE_NONE ? (T) body : null));
|
||||
new ResponseEntity<>(
|
||||
body != VALUE_NONE ? (T) body : null,
|
||||
response.headers().asHttpHeaders(),
|
||||
response.rawStatusCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,15 +61,7 @@ abstract class WebClientUtils {
|
|||
*/
|
||||
public static <T> Mono<ResponseEntity<List<T>>> mapToEntityList(ClientResponse response, Publisher<T> body) {
|
||||
return Flux.from(body).collectList().map(list ->
|
||||
ResponseEntity.status(response.rawStatusCode())
|
||||
.headers(response.headers().asHttpHeaders())
|
||||
.body(list));
|
||||
new ResponseEntity<>(list, response.headers().asHttpHeaders(), response.rawStatusCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the given exception should be wrapped.
|
||||
*/
|
||||
public static boolean shouldWrapException(Throwable t) {
|
||||
return !(t instanceof WebClientException) && !(t instanceof CodecException);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue