From 24ebb5ecd5ebc778426839e757b4665d32f1d28a Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 10 Nov 2021 16:23:41 +0100 Subject: [PATCH] Use ByteArrayDecoder in DefaultClientResponse::createException This commit changes DefaultClientResponse::createException to use the ByteArrayDecoder, instead of converting to DataBuffers and turning these into a byte array. Closes gh-27666 --- .../client/DefaultClientResponse.java | 8 +---- .../client/DefaultClientResponseTests.java | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java index f818e47568f..ed1148d7c8b 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java @@ -187,13 +187,7 @@ class DefaultClientResponse implements ClientResponse { @Override public Mono createException() { - return DataBufferUtils.join(body(BodyExtractors.toDataBuffers())) - .map(dataBuffer -> { - byte[] bytes = new byte[dataBuffer.readableByteCount()]; - dataBuffer.read(bytes); - DataBufferUtils.release(dataBuffer); - return bytes; - }) + return bodyToMono(byte[].class) .defaultIfEmpty(new byte[0]) .map(bodyBytes -> { HttpRequest request = this.requestSupplier.get(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java index ed05d7b2d74..82da37ba234 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java @@ -30,6 +30,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.codec.ByteArrayDecoder; import org.springframework.core.codec.StringDecoder; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DefaultDataBuffer; @@ -48,6 +49,7 @@ import org.springframework.util.MultiValueMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.entry; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.springframework.web.reactive.function.BodyExtractors.toMono; @@ -340,6 +342,33 @@ public class DefaultClientResponseTests { assertThat(result.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_PLAIN); } + @Test + public void createException() { + DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); + byte[] bytes = "foo".getBytes(StandardCharsets.UTF_8); + DefaultDataBuffer dataBuffer = factory.wrap(ByteBuffer.wrap(bytes)); + Flux body = Flux.just(dataBuffer); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.TEXT_PLAIN); + given(mockResponse.getHeaders()).willReturn(httpHeaders); + given(mockResponse.getStatusCode()).willReturn(HttpStatus.NOT_FOUND); + given(mockResponse.getRawStatusCode()).willReturn(HttpStatus.NOT_FOUND.value()); + given(mockResponse.getBody()).willReturn(body); + + List> messageReaders = Collections.singletonList( + new DecoderHttpMessageReader<>(new ByteArrayDecoder())); + given(mockExchangeStrategies.messageReaders()).willReturn(messageReaders); + + Mono resultMono = defaultClientResponse.createException(); + WebClientResponseException exception = resultMono.block(); + assertThat(exception.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(exception.getMessage()).isEqualTo("404 Not Found"); + assertThat(exception.getHeaders()).containsExactly(entry("Content-Type", + Collections.singletonList("text/plain"))); + assertThat(exception.getResponseBodyAsByteArray()).isEqualTo(bytes); + } + private void mockTextPlainResponse(Flux body) { HttpHeaders httpHeaders = new HttpHeaders();