Add toBodilessEntity to ClientResponse and WebClient.ResponseSpec

See gh-23498
This commit is contained in:
Arjen Poutsma
2019-09-02 12:25:18 +02:00
parent f5640cbfe0
commit 37398c669c
8 changed files with 147 additions and 3 deletions

View File

@@ -59,6 +59,7 @@ import org.springframework.web.reactive.function.BodyExtractor;
* {@link #toEntity(ParameterizedTypeReference)}</li>
* <li>{@link #toEntityList(Class)} or
* {@link #toEntityList(ParameterizedTypeReference)}</li>
* <li>{@link #toBodilessEntity()}</li>
* <li>{@link #releaseBody()}</li>
* </ul>
* You can use {@code bodyToMono(Void.class)} if no response content is
@@ -184,6 +185,15 @@ public interface ClientResponse {
*/
<T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef);
/**
* Return this response as a delayed {@code ResponseEntity} containing
* status and headers, but no body. Calling this method will
* {@linkplain #releaseBody() release} the body of the response.
* @return {@code Mono} with the bodiless {@code ResponseEntity}
* @since 5.2
*/
Mono<ResponseEntity<Void>> toBodilessEntity();
/**
* Creates a {@link WebClientResponseException} based on the status code,
* headers, and body of this response as well as the corresponding request.

View File

@@ -162,6 +162,12 @@ class DefaultClientResponse implements ClientResponse {
.then();
}
@Override
public Mono<ResponseEntity<Void>> toBodilessEntity() {
return releaseBody()
.then(WebClientUtils.toEntity(this, Mono.empty()));
}
@Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
return WebClientUtils.toEntity(this, bodyToMono(bodyType));

View File

@@ -562,6 +562,14 @@ class DefaultWebClient implements WebClient {
handleBodyFlux(response, response.bodyToFlux(elementTypeRef))));
}
@Override
public Mono<ResponseEntity<Void>> toBodilessEntity() {
return this.responseMono.flatMap(response ->
WebClientUtils.toEntity(response, handleBodyMono(response, Mono.<Void>empty()))
.doOnNext(entity -> response.releaseBody()) // body is drained in other cases
);
}
private static class StatusHandler {

View File

@@ -751,6 +751,18 @@ public interface WebClient {
* @since 5.2
*/
<T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef);
/**
* Return the response as a delayed {@code ResponseEntity} containing status and headers,
* but no body. By default, if the response has status code 4xx or 5xx, the {@code Mono}
* will contain a {@link WebClientException}. This can be overridden with
* {@link #onStatus(Predicate, Function)}.
* Calling this method will {@linkplain ClientResponse#releaseBody() release} the body of
* the response.
* @return {@code Mono} with the bodiless {@code ResponseEntity}
* @since 5.2
*/
Mono<ResponseEntity<Void>> toBodilessEntity();
}

View File

@@ -44,8 +44,7 @@ abstract class WebClientUtils {
int status = response.rawStatusCode();
return bodyMono
.map(body -> createEntity(body, headers, status))
.switchIfEmpty(Mono.defer(
() -> Mono.just(createEntity(null, headers, status))));
.switchIfEmpty(Mono.fromCallable( () -> createEntity(null, headers, status)));
});
}
@@ -62,7 +61,7 @@ abstract class WebClientUtils {
});
}
private static <T> ResponseEntity<T> createEntity(@Nullable T body, HttpHeaders headers, int 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)

View File

@@ -123,6 +123,11 @@ public class ClientResponseWrapper implements ClientResponse {
return this.delegate.releaseBody();
}
@Override
public Mono<ResponseEntity<Void>> toBodilessEntity() {
return this.delegate.toBodilessEntity();
}
@Override
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyType) {
return this.delegate.toEntity(bodyType);