Consistent handling of 4xx/5xx status codes in WebClient

This commit changes the handling of 4xx/5xx status codes in the
WebClient to the following simple rule: if there is no way for the user
to get the response status code, then a WebClientException is returned.
If there is a way to get to the status code, then we do not return an
exception.

Issue: SPR-15486
This commit is contained in:
Arjen Poutsma
2017-04-26 17:33:21 +02:00
parent 0e7d6fc4d1
commit 4a8c99c9ce
6 changed files with 93 additions and 83 deletions

View File

@@ -29,7 +29,6 @@ import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DataBuffer;
@@ -48,7 +47,7 @@ import org.springframework.util.MultiValueMap;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.springframework.web.reactive.function.BodyExtractors.*;
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
/**
* @author Arjen Poutsma
@@ -151,24 +150,6 @@ public class DefaultClientResponseTests {
assertEquals("foo", resultMono.block());
}
@Test
public void bodyToMonoError() throws Exception {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_PLAIN);
when(mockResponse.getHeaders()).thenReturn(httpHeaders);
when(mockResponse.getStatusCode()).thenReturn(HttpStatus.NOT_FOUND);
Set<HttpMessageReader<?>> messageReaders = Collections
.singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true)));
when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Mono<String> resultMono = defaultClientResponse.bodyToMono(String.class);
StepVerifier.create(resultMono)
.expectError(WebClientException.class)
.verify();
}
@Test
public void bodyToFlux() throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
@@ -191,21 +172,4 @@ public class DefaultClientResponseTests {
assertEquals(Collections.singletonList("foo"), result.block());
}
@Test
public void bodyToFluxError() throws Exception {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_PLAIN);
when(mockResponse.getHeaders()).thenReturn(httpHeaders);
when(mockResponse.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);
Set<HttpMessageReader<?>> messageReaders = Collections
.singleton(new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes(true)));
when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Flux<String> resultFlux = defaultClientResponse.bodyToFlux(String.class);
StepVerifier.create(resultFlux)
.expectError(WebClientException.class)
.verify();
}
}

View File

@@ -334,7 +334,7 @@ public class WebClientIntegrationTests {
}
@Test
public void notFound() throws Exception {
public void exchangeNotFound() throws Exception {
this.server.enqueue(new MockResponse().setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
@@ -351,6 +351,47 @@ public class WebClientIntegrationTests {
Assert.assertEquals("/greeting?name=Spring", recordedRequest.getPath());
}
@Test
public void retrieveBodyToMonoNotFound() throws Exception {
this.server.enqueue(new MockResponse().setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
Mono<String> result = this.webClient.get()
.uri("/greeting?name=Spring")
.retrieve()
.bodyToMono(String.class);
StepVerifier.create(result)
.expectError(WebClientException.class)
.verify(Duration.ofSeconds(3));
RecordedRequest recordedRequest = server.takeRequest();
Assert.assertEquals(1, server.getRequestCount());
Assert.assertEquals("*/*", recordedRequest.getHeader(HttpHeaders.ACCEPT));
Assert.assertEquals("/greeting?name=Spring", recordedRequest.getPath());
}
@Test
public void retrieveToEntityNotFound() throws Exception {
this.server.enqueue(new MockResponse().setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
Mono<ResponseEntity<String>> result = this.webClient.get()
.uri("/greeting?name=Spring")
.retrieve()
.toEntity(String.class);
StepVerifier.create(result)
.consumeNextWith(response -> assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()))
.expectComplete()
.verify(Duration.ofSeconds(3));
RecordedRequest recordedRequest = server.takeRequest();
Assert.assertEquals(1, server.getRequestCount());
Assert.assertEquals("*/*", recordedRequest.getHeader(HttpHeaders.ACCEPT));
Assert.assertEquals("/greeting?name=Spring", recordedRequest.getPath());
}
@Test
public void buildFilter() throws Exception {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));