Merge branch '5.2.x'
# Conflicts: # build.gradle # spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java # spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/server/reactive/MockServerHttpRequest.java # spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java
This commit is contained in:
commit
a34f1e3759
|
@ -151,7 +151,7 @@ configure(allprojects) { project ->
|
||||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
dependency("org.apache.httpcomponents:httpasyncclient:4.1.4") {
|
||||||
exclude group: "commons-logging", name: "commons-logging"
|
exclude group: "commons-logging", name: "commons-logging"
|
||||||
}
|
}
|
||||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.2"
|
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.3"
|
||||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.0'
|
dependency 'org.apache.httpcomponents.client5:httpclient5:5.0'
|
||||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.0'
|
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.0'
|
||||||
|
|
||||||
|
|
|
@ -76,15 +76,15 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private MockServerHttpRequest(String httpMethod,
|
private MockServerHttpRequest(String httpMethod,
|
||||||
URI uri, @Nullable String contextPath, HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
URI uri, @Nullable String contextPath, HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
||||||
@Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress,
|
@Nullable InetSocketAddress localAddress, @Nullable InetSocketAddress remoteAddress,
|
||||||
@Nullable SslInfo sslInfo, Publisher<? extends DataBuffer> body) {
|
@Nullable SslInfo sslInfo, Publisher<? extends DataBuffer> body) {
|
||||||
|
|
||||||
super(uri, contextPath, headers);
|
super(uri, contextPath, headers);
|
||||||
Assert.isTrue(StringUtils.hasText(httpMethod), "HTTP method is required.");
|
Assert.isTrue(StringUtils.hasText(httpMethod), "HTTP method is required.");
|
||||||
this.httpMethod = httpMethod;
|
this.httpMethod = httpMethod;
|
||||||
this.cookies = cookies;
|
this.cookies = cookies;
|
||||||
this.remoteAddress = remoteAddress;
|
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
|
this.remoteAddress = remoteAddress;
|
||||||
this.sslInfo = sslInfo;
|
this.sslInfo = sslInfo;
|
||||||
this.body = Flux.from(body);
|
this.body = Flux.from(body);
|
||||||
}
|
}
|
||||||
|
@ -382,9 +382,9 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
* @see BodyBuilder#body(String)
|
* @see BodyBuilder#body(String)
|
||||||
*/
|
*/
|
||||||
MockServerHttpRequest build();
|
MockServerHttpRequest build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder that adds a body to the request.
|
* A builder that adds a body to the request.
|
||||||
*/
|
*/
|
||||||
|
@ -423,7 +423,6 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
* @return the built request entity
|
* @return the built request entity
|
||||||
*/
|
*/
|
||||||
MockServerHttpRequest body(String body);
|
MockServerHttpRequest body(String body);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -597,7 +596,7 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
||||||
applyCookiesIfNecessary();
|
applyCookiesIfNecessary();
|
||||||
return new MockServerHttpRequest(this.methodValue, getUrlToUse(), this.contextPath,
|
return new MockServerHttpRequest(this.methodValue, getUrlToUse(), this.contextPath,
|
||||||
this.headers, this.cookies, this.remoteAddress, this.localAddress, this.sslInfo, body);
|
this.headers, this.cookies, this.localAddress, this.remoteAddress, this.sslInfo, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCookiesIfNecessary() {
|
private void applyCookiesIfNecessary() {
|
||||||
|
@ -610,11 +609,9 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
private URI getUrlToUse() {
|
private URI getUrlToUse() {
|
||||||
MultiValueMap<String, String> params =
|
MultiValueMap<String, String> params =
|
||||||
this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
|
this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
|
||||||
|
|
||||||
if (!params.isEmpty()) {
|
if (!params.isEmpty()) {
|
||||||
return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
|
return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.url;
|
return this.url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ import org.springframework.web.util.UriTemplateHandler;
|
||||||
* @param <T> the body type
|
* @param <T> the body type
|
||||||
* @see #getMethod()
|
* @see #getMethod()
|
||||||
* @see #getUrl()
|
* @see #getUrl()
|
||||||
|
* @see org.springframework.web.client.RestOperations#exchange(RequestEntity, Class)
|
||||||
|
* @see ResponseEntity
|
||||||
*/
|
*/
|
||||||
public class RequestEntity<T> extends HttpEntity<T> {
|
public class RequestEntity<T> extends HttpEntity<T> {
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -70,6 +70,10 @@ import org.springframework.util.ObjectUtils;
|
||||||
* @since 3.0.2
|
* @since 3.0.2
|
||||||
* @param <T> the body type
|
* @param <T> the body type
|
||||||
* @see #getStatusCode()
|
* @see #getStatusCode()
|
||||||
|
* @see org.springframework.web.client.RestOperations#getForEntity(String, Class, Object...)
|
||||||
|
* @see org.springframework.web.client.RestOperations#getForEntity(String, Class, java.util.Map)
|
||||||
|
* @see org.springframework.web.client.RestOperations#getForEntity(URI, Class)
|
||||||
|
* @see RequestEntity
|
||||||
*/
|
*/
|
||||||
public class ResponseEntity<T> extends HttpEntity<T> {
|
public class ResponseEntity<T> extends HttpEntity<T> {
|
||||||
|
|
||||||
|
@ -217,19 +221,6 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||||
return new DefaultBuilder(status);
|
return new DefaultBuilder(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for creating a {@code ResponseEntity} with the given body
|
|
||||||
* and the {@linkplain HttpStatus#OK OK} status, or an empty body and a
|
|
||||||
* {@linkplain HttpStatus#NOT_FOUND NOT FOUND} status in case of an
|
|
||||||
* {@linkplain Optional#empty()} parameter.
|
|
||||||
* @return the created {@code ResponseEntity}
|
|
||||||
* @since 5.1
|
|
||||||
*/
|
|
||||||
public static <T> ResponseEntity<T> of(Optional<T> body) {
|
|
||||||
Assert.notNull(body, "Body must not be null");
|
|
||||||
return body.map(ResponseEntity::ok).orElse(notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a builder with the status set to {@linkplain HttpStatus#OK OK}.
|
* Create a builder with the status set to {@linkplain HttpStatus#OK OK}.
|
||||||
* @return the created builder
|
* @return the created builder
|
||||||
|
@ -246,8 +237,20 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public static <T> ResponseEntity<T> ok(T body) {
|
public static <T> ResponseEntity<T> ok(T body) {
|
||||||
BodyBuilder builder = ok();
|
return ok().body(body);
|
||||||
return builder.body(body);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A shortcut for creating a {@code ResponseEntity} with the given body
|
||||||
|
* and the {@linkplain HttpStatus#OK OK} status, or an empty body and a
|
||||||
|
* {@linkplain HttpStatus#NOT_FOUND NOT FOUND} status in case of an
|
||||||
|
* {@linkplain Optional#empty()} parameter.
|
||||||
|
* @return the created {@code ResponseEntity}
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public static <T> ResponseEntity<T> of(Optional<T> body) {
|
||||||
|
Assert.notNull(body, "Body must not be null");
|
||||||
|
return body.map(ResponseEntity::ok).orElseGet(() -> notFound().build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,8 +261,7 @@ public class ResponseEntity<T> extends HttpEntity<T> {
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public static BodyBuilder created(URI location) {
|
public static BodyBuilder created(URI location) {
|
||||||
BodyBuilder builder = status(HttpStatus.CREATED);
|
return status(HttpStatus.CREATED).location(location);
|
||||||
return builder.location(location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -76,15 +76,15 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
|
|
||||||
private MockServerHttpRequest(String httpMethod,
|
private MockServerHttpRequest(String httpMethod,
|
||||||
URI uri, @Nullable String contextPath, HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
URI uri, @Nullable String contextPath, HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
||||||
@Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress,
|
@Nullable InetSocketAddress localAddress, @Nullable InetSocketAddress remoteAddress,
|
||||||
@Nullable SslInfo sslInfo, Publisher<? extends DataBuffer> body) {
|
@Nullable SslInfo sslInfo, Publisher<? extends DataBuffer> body) {
|
||||||
|
|
||||||
super(uri, contextPath, headers);
|
super(uri, contextPath, headers);
|
||||||
Assert.isTrue(StringUtils.hasText(httpMethod), "HTTP method is required.");
|
Assert.isTrue(StringUtils.hasText(httpMethod), "HTTP method is required.");
|
||||||
this.httpMethod = httpMethod;
|
this.httpMethod = httpMethod;
|
||||||
this.cookies = cookies;
|
this.cookies = cookies;
|
||||||
this.remoteAddress = remoteAddress;
|
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
|
this.remoteAddress = remoteAddress;
|
||||||
this.sslInfo = sslInfo;
|
this.sslInfo = sslInfo;
|
||||||
this.body = Flux.from(body);
|
this.body = Flux.from(body);
|
||||||
}
|
}
|
||||||
|
@ -382,9 +382,9 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
* @see BodyBuilder#body(String)
|
* @see BodyBuilder#body(String)
|
||||||
*/
|
*/
|
||||||
MockServerHttpRequest build();
|
MockServerHttpRequest build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder that adds a body to the request.
|
* A builder that adds a body to the request.
|
||||||
*/
|
*/
|
||||||
|
@ -423,7 +423,6 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
* @return the built request entity
|
* @return the built request entity
|
||||||
*/
|
*/
|
||||||
MockServerHttpRequest body(String body);
|
MockServerHttpRequest body(String body);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -597,7 +596,7 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
||||||
applyCookiesIfNecessary();
|
applyCookiesIfNecessary();
|
||||||
return new MockServerHttpRequest(this.methodValue, getUrlToUse(), this.contextPath,
|
return new MockServerHttpRequest(this.methodValue, getUrlToUse(), this.contextPath,
|
||||||
this.headers, this.cookies, this.remoteAddress, this.localAddress, this.sslInfo, body);
|
this.headers, this.cookies, this.localAddress, this.remoteAddress, this.sslInfo, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCookiesIfNecessary() {
|
private void applyCookiesIfNecessary() {
|
||||||
|
@ -610,11 +609,9 @@ public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||||
private URI getUrlToUse() {
|
private URI getUrlToUse() {
|
||||||
MultiValueMap<String, String> params =
|
MultiValueMap<String, String> params =
|
||||||
this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
|
this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
|
||||||
|
|
||||||
if (!params.isEmpty()) {
|
if (!params.isEmpty()) {
|
||||||
return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
|
return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.url;
|
return this.url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
||||||
ServerCodecConfigurer serverCodecConfigurer,
|
ServerCodecConfigurer serverCodecConfigurer,
|
||||||
@Qualifier("webFluxConversionService") FormattingConversionService conversionService,
|
@Qualifier("webFluxConversionService") FormattingConversionService conversionService,
|
||||||
@Qualifier("webFluxValidator") Validator validator) {
|
@Qualifier("webFluxValidator") Validator validator) {
|
||||||
|
|
||||||
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
|
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
|
||||||
adapter.setMessageReaders(serverCodecConfigurer.getReaders());
|
adapter.setMessageReaders(serverCodecConfigurer.getReaders());
|
||||||
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
|
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
|
||||||
|
|
|
@ -417,26 +417,23 @@ class DefaultWebClient implements WebClient {
|
||||||
|
|
||||||
private static class DefaultResponseSpec implements ResponseSpec {
|
private static class DefaultResponseSpec implements ResponseSpec {
|
||||||
|
|
||||||
private static final IntPredicate STATUS_CODE_ERROR = value -> value >= 400;
|
private static final IntPredicate STATUS_CODE_ERROR = (value -> value >= 400);
|
||||||
|
|
||||||
private static final StatusHandler DEFAULT_STATUS_HANDLER =
|
private static final StatusHandler DEFAULT_STATUS_HANDLER =
|
||||||
new StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException);
|
new StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException);
|
||||||
|
|
||||||
|
|
||||||
private final Mono<ClientResponse> responseMono;
|
private final Mono<ClientResponse> responseMono;
|
||||||
|
|
||||||
private final Supplier<HttpRequest> requestSupplier;
|
private final Supplier<HttpRequest> requestSupplier;
|
||||||
|
|
||||||
private final List<StatusHandler> statusHandlers = new ArrayList<>(1);
|
private final List<StatusHandler> statusHandlers = new ArrayList<>(1);
|
||||||
|
|
||||||
|
|
||||||
DefaultResponseSpec(Mono<ClientResponse> responseMono, Supplier<HttpRequest> requestSupplier) {
|
DefaultResponseSpec(Mono<ClientResponse> responseMono, Supplier<HttpRequest> requestSupplier) {
|
||||||
this.responseMono = responseMono;
|
this.responseMono = responseMono;
|
||||||
this.requestSupplier = requestSupplier;
|
this.requestSupplier = requestSupplier;
|
||||||
this.statusHandlers.add(DEFAULT_STATUS_HANDLER);
|
this.statusHandlers.add(DEFAULT_STATUS_HANDLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate,
|
public ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate,
|
||||||
Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
|
Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
|
||||||
|
|
|
@ -106,6 +106,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||||
this.defaultUriVariables = (other.defaultUriVariables != null ?
|
this.defaultUriVariables = (other.defaultUriVariables != null ?
|
||||||
new LinkedHashMap<>(other.defaultUriVariables) : null);
|
new LinkedHashMap<>(other.defaultUriVariables) : null);
|
||||||
this.uriBuilderFactory = other.uriBuilderFactory;
|
this.uriBuilderFactory = other.uriBuilderFactory;
|
||||||
|
|
||||||
if (other.defaultHeaders != null) {
|
if (other.defaultHeaders != null) {
|
||||||
this.defaultHeaders = new HttpHeaders();
|
this.defaultHeaders = new HttpHeaders();
|
||||||
this.defaultHeaders.putAll(other.defaultHeaders);
|
this.defaultHeaders.putAll(other.defaultHeaders);
|
||||||
|
@ -113,13 +114,16 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||||
else {
|
else {
|
||||||
this.defaultHeaders = null;
|
this.defaultHeaders = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.defaultCookies = (other.defaultCookies != null ?
|
this.defaultCookies = (other.defaultCookies != null ?
|
||||||
new LinkedMultiValueMap<>(other.defaultCookies) : null);
|
new LinkedMultiValueMap<>(other.defaultCookies) : null);
|
||||||
this.defaultRequest = other.defaultRequest;
|
this.defaultRequest = other.defaultRequest;
|
||||||
this.filters = other.filters != null ? new ArrayList<>(other.filters) : null;
|
this.filters = (other.filters != null ? new ArrayList<>(other.filters) : null);
|
||||||
|
|
||||||
this.connector = other.connector;
|
this.connector = other.connector;
|
||||||
this.strategies = other.strategies;
|
this.strategies = other.strategies;
|
||||||
this.strategiesConfigurers = other.strategiesConfigurers != null ? new ArrayList<>(other.strategiesConfigurers) : null;
|
this.strategiesConfigurers = (other.strategiesConfigurers != null ?
|
||||||
|
new ArrayList<>(other.strategiesConfigurers) : null);
|
||||||
this.exchangeFunction = other.exchangeFunction;
|
this.exchangeFunction = other.exchangeFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +292,10 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||||
|
|
||||||
private ExchangeStrategies initExchangeStrategies() {
|
private ExchangeStrategies initExchangeStrategies() {
|
||||||
if (CollectionUtils.isEmpty(this.strategiesConfigurers)) {
|
if (CollectionUtils.isEmpty(this.strategiesConfigurers)) {
|
||||||
return this.strategies != null ? this.strategies : ExchangeStrategies.withDefaults();
|
return (this.strategies != null ? this.strategies : ExchangeStrategies.withDefaults());
|
||||||
}
|
}
|
||||||
ExchangeStrategies.Builder builder =
|
ExchangeStrategies.Builder builder =
|
||||||
this.strategies != null ? this.strategies.mutate() : ExchangeStrategies.builder();
|
(this.strategies != null ? this.strategies.mutate() : ExchangeStrategies.builder());
|
||||||
this.strategiesConfigurers.forEach(configurer -> configurer.accept(builder));
|
this.strategiesConfigurers.forEach(configurer -> configurer.accept(builder));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
@ -300,8 +304,8 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||||
if (this.uriBuilderFactory != null) {
|
if (this.uriBuilderFactory != null) {
|
||||||
return this.uriBuilderFactory;
|
return this.uriBuilderFactory;
|
||||||
}
|
}
|
||||||
DefaultUriBuilderFactory factory = this.baseUrl != null ?
|
DefaultUriBuilderFactory factory = (this.baseUrl != null ?
|
||||||
new DefaultUriBuilderFactory(this.baseUrl) : new DefaultUriBuilderFactory();
|
new DefaultUriBuilderFactory(this.baseUrl) : new DefaultUriBuilderFactory());
|
||||||
factory.setDefaultUriVariables(this.defaultUriVariables);
|
factory.setDefaultUriVariables(this.defaultUriVariables);
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue