Minor refactoring and polishing in WebClientUtils

See: gh-24788
This commit is contained in:
Rossen Stoyanchev 2020-03-26 11:13:00 +00:00
parent 6222efc54b
commit d1cf16320b
3 changed files with 33 additions and 47 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -157,35 +157,32 @@ class DefaultClientResponse implements ClientResponse {
@Override @Override
public Mono<Void> releaseBody() { public Mono<Void> releaseBody() {
return body(BodyExtractors.toDataBuffers()) return body(BodyExtractors.toDataBuffers()).map(DataBufferUtils::release).then();
.map(DataBufferUtils::release)
.then();
} }
@Override @Override
public Mono<ResponseEntity<Void>> toBodilessEntity() { public Mono<ResponseEntity<Void>> toBodilessEntity() {
return releaseBody() return releaseBody().then(WebClientUtils.mapToEntity(this, Mono.empty()));
.then(WebClientUtils.toEntity(this, Mono.empty()));
} }
@Override @Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) { public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
return WebClientUtils.toEntity(this, bodyToMono(bodyType)); return WebClientUtils.mapToEntity(this, bodyToMono(bodyType));
} }
@Override @Override
public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeReference) { public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeReference) {
return WebClientUtils.toEntity(this, bodyToMono(bodyTypeReference)); return WebClientUtils.mapToEntity(this, bodyToMono(bodyTypeReference));
} }
@Override @Override
public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) { public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) {
return WebClientUtils.toEntityList(this, bodyToFlux(elementClass)); return WebClientUtils.mapToEntityList(this, bodyToFlux(elementClass));
} }
@Override @Override
public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) { public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) {
return WebClientUtils.toEntityList(this, bodyToFlux(elementTypeRef)); return WebClientUtils.mapToEntityList(this, bodyToFlux(elementTypeRef));
} }
@Override @Override

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -546,34 +546,35 @@ class DefaultWebClient implements WebClient {
@Override @Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyClass) { public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyClass) {
return this.responseMono.flatMap(response -> return this.responseMono.flatMap(response ->
WebClientUtils.toEntity(response, handleBodyMono(response, response.bodyToMono(bodyClass)))); WebClientUtils.mapToEntity(response,
handleBodyMono(response, response.bodyToMono(bodyClass))));
} }
@Override @Override
public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeReference) { public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeRef) {
return this.responseMono.flatMap(response -> return this.responseMono.flatMap(response ->
WebClientUtils.toEntity(response, WebClientUtils.mapToEntity(response,
handleBodyMono(response, response.bodyToMono(bodyTypeReference)))); handleBodyMono(response, response.bodyToMono(bodyTypeRef))));
} }
@Override @Override
public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) { public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) {
return this.responseMono.flatMap(response -> return this.responseMono.flatMap(response ->
WebClientUtils.toEntityList(response, WebClientUtils.mapToEntityList(response,
handleBodyFlux(response, response.bodyToFlux(elementClass)))); handleBodyFlux(response, response.bodyToFlux(elementClass))));
} }
@Override @Override
public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) { public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) {
return this.responseMono.flatMap(response -> return this.responseMono.flatMap(response ->
WebClientUtils.toEntityList(response, WebClientUtils.mapToEntityList(response,
handleBodyFlux(response, response.bodyToFlux(elementTypeRef)))); handleBodyFlux(response, response.bodyToFlux(elementTypeRef))));
} }
@Override @Override
public Mono<ResponseEntity<Void>> toBodilessEntity() { public Mono<ResponseEntity<Void>> toBodilessEntity() {
return this.responseMono.flatMap(response -> return this.responseMono.flatMap(response ->
WebClientUtils.toEntity(response, handleBodyMono(response, Mono.<Void>empty())) WebClientUtils.mapToEntity(response, handleBodyMono(response, Mono.<Void>empty()))
.doOnNext(entity -> response.releaseBody()) // body is drained in other cases .doOnNext(entity -> response.releaseBody()) // body is drained in other cases
); );
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +22,7 @@ import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
/** /**
* Internal methods shared between {@link DefaultWebClient} and {@link DefaultClientResponse}. * Internal methods shared between {@link DefaultWebClient} and {@link DefaultClientResponse}.
@ -35,37 +32,28 @@ import org.springframework.lang.Nullable;
*/ */
abstract class WebClientUtils { 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";
/** /**
* Create a delayed {@link ResponseEntity} from the given response and body. * Map the given response to a single value {@code ResponseEntity<T>}.
*/ */
public static <T> Mono<ResponseEntity<T>> toEntity(ClientResponse response, Mono<T> bodyMono) { @SuppressWarnings("unchecked")
return Mono.defer(() -> { public static <T> Mono<ResponseEntity<T>> mapToEntity(ClientResponse response, Mono<T> bodyMono) {
HttpHeaders headers = response.headers().asHttpHeaders(); return ((Mono<Object>) bodyMono).defaultIfEmpty(VALUE_NONE).map(body ->
int status = response.rawStatusCode(); ResponseEntity.status(response.rawStatusCode())
return bodyMono .headers(response.headers().asHttpHeaders())
.map(body -> createEntity(body, headers, status)) .body(body != VALUE_NONE ? (T) body : null));
.switchIfEmpty(Mono.fromCallable( () -> createEntity(null, headers, status)));
});
} }
/** /**
* Create a delayed {@link ResponseEntity} list from the given response and body. * Map the given response to a {@code ResponseEntity<List<T>>}.
*/ */
public static <T> Mono<ResponseEntity<List<T>>> toEntityList(ClientResponse response, Publisher<T> body) { public static <T> Mono<ResponseEntity<List<T>>> mapToEntityList(ClientResponse response, Publisher<T> body) {
return Mono.defer(() -> { return Flux.from(body).collectList().map(list ->
HttpHeaders headers = response.headers().asHttpHeaders(); ResponseEntity.status(response.rawStatusCode())
int status = response.rawStatusCode(); .headers(response.headers().asHttpHeaders())
return Flux.from(body) .body(list));
.collectList()
.map(list -> createEntity(list, headers, status));
});
}
public static <T> ResponseEntity<T> createEntity(@Nullable T body, HttpHeaders headers, int status) {
HttpStatus resolvedStatus = HttpStatus.resolve(status);
return resolvedStatus != null
? new ResponseEntity<>(body, headers, resolvedStatus)
: ResponseEntity.status(status).headers(headers).body(body);
} }
} }