Expose request in WebClientResponseException

This commit exposes the request that lead to it in
WebClientResponseException, as a HttpRequest object.

Issue: SPR-17087
This commit is contained in:
Arjen Poutsma 2018-12-07 11:04:18 +01:00
parent 54f5b7d0ee
commit 3258ac1ec4
4 changed files with 205 additions and 70 deletions

View File

@ -27,9 +27,11 @@ import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@ -39,6 +41,7 @@ import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpRequest;
@ -139,7 +142,6 @@ class DefaultWebClient implements WebClient {
return methodInternal(httpMethod);
}
@SuppressWarnings("unchecked")
private RequestBodyUriSpec methodInternal(HttpMethod httpMethod) {
return new DefaultRequestBodyUriSpec(httpMethod);
}
@ -364,7 +366,35 @@ class DefaultWebClient implements WebClient {
@Override
public ResponseSpec retrieve() {
return new DefaultResponseSpec(exchange());
return new DefaultResponseSpec(exchange(), this::createRequest);
}
private HttpRequest createRequest() {
return new HttpRequest() {
private HttpHeaders headers = initHeaders();
@Override
public HttpMethod getMethod() {
return httpMethod;
}
@Override
public String getMethodValue() {
return httpMethod.name();
}
@Override
public URI getURI() {
return uri;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
};
}
}
@ -376,11 +406,15 @@ class DefaultWebClient implements WebClient {
private final Mono<ClientResponse> responseMono;
private final Supplier<HttpRequest> requestSupplier;
private final List<StatusHandler> statusHandlers = new ArrayList<>(1);
DefaultResponseSpec(Mono<ClientResponse> responseMono) {
DefaultResponseSpec(Mono<ClientResponse> responseMono,
Supplier<HttpRequest> requestSupplier) {
this.responseMono = responseMono;
this.requestSupplier = requestSupplier;
this.statusHandlers.add(DEFAULT_STATUS_HANDLER);
}
@ -393,7 +427,8 @@ class DefaultWebClient implements WebClient {
if (this.statusHandlers.size() == 1 && this.statusHandlers.get(0) == DEFAULT_STATUS_HANDLER) {
this.statusHandlers.clear();
}
this.statusHandlers.add(new StatusHandler(statusPredicate, exceptionFunction));
this.statusHandlers.add(new StatusHandler(statusPredicate,
(clientResponse, request) -> exceptionFunction.apply(clientResponse)));
return this;
}
@ -405,21 +440,18 @@ class DefaultWebClient implements WebClient {
}
@Override
@SuppressWarnings("unchecked")
public <T> Mono<T> bodyToMono(ParameterizedTypeReference<T> bodyType) {
return this.responseMono.flatMap(response ->
handleBody(response, response.bodyToMono(bodyType), mono -> mono.flatMap(Mono::error)));
}
@Override
@SuppressWarnings("unchecked")
public <T> Flux<T> bodyToFlux(Class<T> elementType) {
return this.responseMono.flatMapMany(response ->
handleBody(response, response.bodyToFlux(elementType), mono -> mono.flatMapMany(Flux::error)));
}
@Override
@SuppressWarnings("unchecked")
public <T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> elementType) {
return this.responseMono.flatMapMany(response -> handleBody(response,
response.bodyToFlux(elementType), mono -> mono.flatMapMany(Flux::error)));
@ -431,7 +463,8 @@ class DefaultWebClient implements WebClient {
if (HttpStatus.resolve(response.rawStatusCode()) != null) {
for (StatusHandler handler : this.statusHandlers) {
if (handler.test(response.statusCode())) {
Mono<? extends Throwable> exMono = handler.apply(response);
HttpRequest request = this.requestSupplier.get();
Mono<? extends Throwable> exMono = handler.apply(response, request);
exMono = exMono.flatMap(ex -> drainBody(response, ex));
exMono = exMono.onErrorResume(ex -> drainBody(response, ex));
return errorFunction.apply(exMono);
@ -440,7 +473,8 @@ class DefaultWebClient implements WebClient {
return bodyPublisher;
}
else {
return errorFunction.apply(createResponseException(response));
return errorFunction.apply(createResponseException(response,
this.requestSupplier.get()));
}
}
@ -452,7 +486,8 @@ class DefaultWebClient implements WebClient {
.onErrorResume(ex2 -> Mono.empty()).thenReturn(ex);
}
private static Mono<WebClientResponseException> createResponseException(ClientResponse response) {
private static Mono<WebClientResponseException> createResponseException(ClientResponse response,
HttpRequest request) {
return DataBufferUtils.join(response.body(BodyExtractors.toDataBuffers()))
.map(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
@ -471,14 +506,16 @@ class DefaultWebClient implements WebClient {
response.statusCode().getReasonPhrase(),
response.headers().asHttpHeaders(),
bodyBytes,
charset);
charset,
request);
}
else {
return new UnknownHttpStatusCodeException(
response.rawStatusCode(),
response.headers().asHttpHeaders(),
bodyBytes,
charset);
charset,
request);
}
});
}
@ -488,11 +525,11 @@ class DefaultWebClient implements WebClient {
private final Predicate<HttpStatus> predicate;
private final Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction;
private final BiFunction<ClientResponse, HttpRequest, Mono<? extends Throwable>> exceptionFunction;
public StatusHandler(Predicate<HttpStatus> predicate,
Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
BiFunction<ClientResponse, HttpRequest, Mono<? extends Throwable>> exceptionFunction) {
Assert.notNull(predicate, "Predicate must not be null");
Assert.notNull(exceptionFunction, "Function must not be null");
@ -505,8 +542,8 @@ class DefaultWebClient implements WebClient {
return this.predicate.test(status);
}
public Mono<? extends Throwable> apply(ClientResponse response) {
return this.exceptionFunction.apply(response);
public Mono<? extends Throwable> apply(ClientResponse response, HttpRequest request) {
return this.exceptionFunction.apply(response, request);
}
}
}

View File

@ -19,6 +19,8 @@ package org.springframework.web.reactive.function.client;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.lang.Nullable;
/**
* Exception thrown when an unknown (or custom) HTTP status code is received.
@ -31,6 +33,10 @@ public class UnknownHttpStatusCodeException extends WebClientResponseException {
private static final long serialVersionUID = 2407169540168185007L;
/**
* Create a new instance of the {@code UnknownHttpStatusCodeException} with the given
* parameters.
*/
public UnknownHttpStatusCodeException(
int statusCode, HttpHeaders headers, byte[] responseBody, Charset responseCharset) {
@ -38,4 +44,17 @@ public class UnknownHttpStatusCodeException extends WebClientResponseException {
headers, responseBody, responseCharset);
}
/**
* Create a new instance of the {@code UnknownHttpStatusCodeException} with the given
* parameters.
* @since 5.1.4
*/
public UnknownHttpStatusCodeException(
int statusCode, HttpHeaders headers, byte[] responseBody, Charset responseCharset,
@Nullable HttpRequest request) {
super("Unknown status code [" + statusCode + "]", statusCode, "",
headers, responseBody, responseCharset, request);
}
}

View File

@ -20,6 +20,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
@ -44,6 +45,9 @@ public class WebClientResponseException extends WebClientException {
private final Charset responseCharset;
@Nullable
private final HttpRequest request;
/**
* Constructor with response data only, and a default message.
@ -52,22 +56,44 @@ public class WebClientResponseException extends WebClientException {
public WebClientResponseException(int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset) {
this(statusCode + " " + statusText, statusCode, statusText, headers, body, charset);
this(statusCode, statusText, headers, body, charset, null);
}
/**
* Constructor with response data only, and a default message.
* @since 5.1.4
*/
public WebClientResponseException(int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
this(statusCode + " " + statusText, statusCode, statusText, headers, body, charset, request);
}
/**
* Constructor with a prepared message.
*/
public WebClientResponseException(String message, int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] responsebody, @Nullable Charset charset) {
@Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset) {
this(message, statusCode, statusText, headers, responseBody, charset, null);
}
/**
* Constructor with a prepared message.
* @since 5.1.4
*/
public WebClientResponseException(String message, int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(message);
this.statusCode = statusCode;
this.statusText = statusText;
this.headers = (headers != null ? headers : HttpHeaders.EMPTY);
this.responseBody = (responsebody != null ? responsebody : new byte[0]);
this.responseBody = (responseBody != null ? responseBody : new byte[0]);
this.responseCharset = (charset != null ? charset : StandardCharsets.ISO_8859_1);
this.request = request;
}
@ -114,6 +140,14 @@ public class WebClientResponseException extends WebClientException {
return new String(this.responseBody, this.responseCharset);
}
/**
* Return the corresponding request.
* @since 5.1.4
*/
@Nullable
public HttpRequest getRequest() {
return this.request;
}
/**
* Create {@code WebClientResponseException} or an HTTP status specific sub-class.
@ -122,44 +156,55 @@ public class WebClientResponseException extends WebClientException {
public static WebClientResponseException create(
int statusCode, String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
return create(statusCode, statusText, headers, body, charset, null);
}
/**
* Create {@code WebClientResponseException} or an HTTP status specific sub-class.
* @since 5.1.4
*/
public static WebClientResponseException create(
int statusCode, String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
HttpStatus httpStatus = HttpStatus.resolve(statusCode);
if (httpStatus != null) {
switch (httpStatus) {
case BAD_REQUEST:
return new WebClientResponseException.BadRequest(statusText, headers, body, charset);
return new WebClientResponseException.BadRequest(statusText, headers, body, charset, request);
case UNAUTHORIZED:
return new WebClientResponseException.Unauthorized(statusText, headers, body, charset);
return new WebClientResponseException.Unauthorized(statusText, headers, body, charset, request);
case FORBIDDEN:
return new WebClientResponseException.Forbidden(statusText, headers, body, charset);
return new WebClientResponseException.Forbidden(statusText, headers, body, charset, request);
case NOT_FOUND:
return new WebClientResponseException.NotFound(statusText, headers, body, charset);
return new WebClientResponseException.NotFound(statusText, headers, body, charset, request);
case METHOD_NOT_ALLOWED:
return new WebClientResponseException.MethodNotAllowed(statusText, headers, body, charset);
return new WebClientResponseException.MethodNotAllowed(statusText, headers, body, charset, request);
case NOT_ACCEPTABLE:
return new WebClientResponseException.NotAcceptable(statusText, headers, body, charset);
return new WebClientResponseException.NotAcceptable(statusText, headers, body, charset, request);
case CONFLICT:
return new WebClientResponseException.Conflict(statusText, headers, body, charset);
return new WebClientResponseException.Conflict(statusText, headers, body, charset, request);
case GONE:
return new WebClientResponseException.Gone(statusText, headers, body, charset);
return new WebClientResponseException.Gone(statusText, headers, body, charset, request);
case UNSUPPORTED_MEDIA_TYPE:
return new WebClientResponseException.UnsupportedMediaType(statusText, headers, body, charset);
return new WebClientResponseException.UnsupportedMediaType(statusText, headers, body, charset, request);
case TOO_MANY_REQUESTS:
return new WebClientResponseException.TooManyRequests(statusText, headers, body, charset);
return new WebClientResponseException.TooManyRequests(statusText, headers, body, charset, request);
case UNPROCESSABLE_ENTITY:
return new WebClientResponseException.UnprocessableEntity(statusText, headers, body, charset);
return new WebClientResponseException.UnprocessableEntity(statusText, headers, body, charset, request);
case INTERNAL_SERVER_ERROR:
return new WebClientResponseException.InternalServerError(statusText, headers, body, charset);
return new WebClientResponseException.InternalServerError(statusText, headers, body, charset, request);
case NOT_IMPLEMENTED:
return new WebClientResponseException.NotImplemented(statusText, headers, body, charset);
return new WebClientResponseException.NotImplemented(statusText, headers, body, charset, request);
case BAD_GATEWAY:
return new WebClientResponseException.BadGateway(statusText, headers, body, charset);
return new WebClientResponseException.BadGateway(statusText, headers, body, charset, request);
case SERVICE_UNAVAILABLE:
return new WebClientResponseException.ServiceUnavailable(statusText, headers, body, charset);
return new WebClientResponseException.ServiceUnavailable(statusText, headers, body, charset, request);
case GATEWAY_TIMEOUT:
return new WebClientResponseException.GatewayTimeout(statusText, headers, body, charset);
return new WebClientResponseException.GatewayTimeout(statusText, headers, body, charset, request);
}
}
return new WebClientResponseException(statusCode, statusText, headers, body, charset);
return new WebClientResponseException(statusCode, statusText, headers, body, charset, request);
}
@ -173,9 +218,11 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class BadRequest extends WebClientResponseException {
BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.BAD_REQUEST.value(), statusText, headers, body, charset);
BadRequest(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.BAD_REQUEST.value(), statusText, headers, body, charset, request);
}
}
/**
@ -185,8 +232,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class Unauthorized extends WebClientResponseException {
Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNAUTHORIZED.value(), statusText, headers, body, charset);
Unauthorized(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.UNAUTHORIZED.value(), statusText, headers, body, charset, request);
}
}
@ -197,8 +245,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class Forbidden extends WebClientResponseException {
Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.FORBIDDEN.value(), statusText, headers, body, charset);
Forbidden(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.FORBIDDEN.value(), statusText, headers, body, charset, request);
}
}
@ -209,8 +258,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class NotFound extends WebClientResponseException {
NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_FOUND.value(), statusText, headers, body, charset);
NotFound(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.NOT_FOUND.value(), statusText, headers, body, charset, request);
}
}
@ -221,8 +271,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class MethodNotAllowed extends WebClientResponseException {
MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.METHOD_NOT_ALLOWED.value(), statusText, headers, body, charset);
MethodNotAllowed(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.METHOD_NOT_ALLOWED.value(), statusText, headers, body, charset,
request);
}
}
@ -233,8 +285,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class NotAcceptable extends WebClientResponseException {
NotAcceptable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_ACCEPTABLE.value(), statusText, headers, body, charset);
NotAcceptable(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.NOT_ACCEPTABLE.value(), statusText, headers, body, charset, request);
}
}
@ -245,8 +298,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class Conflict extends WebClientResponseException {
Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.CONFLICT.value(), statusText, headers, body, charset);
Conflict(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.CONFLICT.value(), statusText, headers, body, charset, request);
}
}
@ -257,8 +311,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class Gone extends WebClientResponseException {
Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.GONE.value(), statusText, headers, body, charset);
Gone(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.GONE.value(), statusText, headers, body, charset, request);
}
}
@ -269,8 +324,11 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class UnsupportedMediaType extends WebClientResponseException {
UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), statusText, headers, body, charset);
UnsupportedMediaType(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), statusText, headers, body, charset,
request);
}
}
@ -281,8 +339,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class UnprocessableEntity extends WebClientResponseException {
UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.UNPROCESSABLE_ENTITY.value(), statusText, headers, body, charset);
UnprocessableEntity(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.UNPROCESSABLE_ENTITY.value(), statusText, headers, body, charset,
request);
}
}
@ -293,8 +353,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class TooManyRequests extends WebClientResponseException {
TooManyRequests(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.TOO_MANY_REQUESTS.value(), statusText, headers, body, charset);
TooManyRequests(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.TOO_MANY_REQUESTS.value(), statusText, headers, body, charset,
request);
}
}
@ -309,8 +371,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class InternalServerError extends WebClientResponseException {
InternalServerError(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.INTERNAL_SERVER_ERROR.value(), statusText, headers, body, charset);
InternalServerError(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.INTERNAL_SERVER_ERROR.value(), statusText, headers, body, charset,
request);
}
}
@ -321,8 +385,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class NotImplemented extends WebClientResponseException {
NotImplemented(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.NOT_IMPLEMENTED.value(), statusText, headers, body, charset);
NotImplemented(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.NOT_IMPLEMENTED.value(), statusText, headers, body, charset, request);
}
}
@ -333,8 +398,9 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class BadGateway extends WebClientResponseException {
BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.BAD_GATEWAY.value(), statusText, headers, body, charset);
BadGateway(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset,
@Nullable HttpRequest request) {
super(HttpStatus.BAD_GATEWAY.value(), statusText, headers, body, charset, request);
}
}
@ -345,8 +411,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class ServiceUnavailable extends WebClientResponseException {
ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.SERVICE_UNAVAILABLE.value(), statusText, headers, body, charset);
ServiceUnavailable(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.SERVICE_UNAVAILABLE.value(), statusText, headers, body, charset,
request);
}
}
@ -357,8 +425,10 @@ public class WebClientResponseException extends WebClientException {
@SuppressWarnings("serial")
public static class GatewayTimeout extends WebClientResponseException {
GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
super(HttpStatus.GATEWAY_TIMEOUT.value(), statusText, headers, body, charset);
GatewayTimeout(String statusText, HttpHeaders headers, byte[] body,
@Nullable Charset charset, @Nullable HttpRequest request) {
super(HttpStatus.GATEWAY_TIMEOUT.value(), statusText, headers, body, charset,
request);
}
}

View File

@ -18,6 +18,7 @@ package org.springframework.web.reactive.function.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.time.Duration;
import java.util.Arrays;
@ -45,6 +46,8 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -494,8 +497,9 @@ public class WebClientIntegrationTests {
prepareResponse(response -> response.setResponseCode(500)
.setHeader("Content-Type", "text/plain").setBody(errorMessage));
String path = "/greeting?name=Spring";
Mono<String> result = this.webClient.get()
.uri("/greeting?name=Spring")
.uri(path)
.retrieve()
.bodyToMono(String.class);
@ -509,13 +513,18 @@ public class WebClientIntegrationTests {
ex.getStatusText());
assertEquals(MediaType.TEXT_PLAIN, ex.getHeaders().getContentType());
assertEquals(errorMessage, ex.getResponseBodyAsString());
HttpRequest request = ex.getRequest();
assertEquals(HttpMethod.GET, request.getMethod());
assertEquals(URI.create(this.server.url(path).toString()), request.getURI());
assertNotNull(request.getHeaders());
})
.verify(Duration.ofSeconds(3));
expectRequestCount(1);
expectRequest(request -> {
assertEquals("*/*", request.getHeader(HttpHeaders.ACCEPT));
assertEquals("/greeting?name=Spring", request.getPath());
assertEquals(path, request.getPath());
});
}