Replace WebClient.filter with Builder.filter

This commit replaces the WebClient.filter method with
WebClient.Builder.filter. The reason for this change is that filters
added via WebClient.filter would be applied in the opposite order of
their declaration, due to the compositional nature of the method,
combined with the immutable nature of the WebClient.
WebClient.Builder.filter does keep the order of the filters, as
registered.

Furthermore, this commit introduces a WebClient.mutate() method,
returning a WebClient.Builder. This method allow to add/remove filters
and other defaults from a given WebClient.

Issue: SPR-15657

Add WebClient.Builder.addFilter

Add Consumer-based headers and cookies methods to builders.

Add WebClient.mutate
This commit is contained in:
Arjen Poutsma
2017-06-19 11:40:10 +02:00
parent 52148a10b7
commit 4a0597d612
9 changed files with 325 additions and 81 deletions

View File

@@ -48,13 +48,14 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriBuilder;
import static java.nio.charset.StandardCharsets.*;
import static org.springframework.test.util.AssertionErrors.*;
import static org.springframework.web.reactive.function.BodyExtractors.*;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.test.util.AssertionErrors.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
/**
* Default implementation of {@link WebTestClient}.
@@ -80,12 +81,6 @@ class DefaultWebTestClient implements WebTestClient {
this.timeout = (timeout != null ? timeout : Duration.ofSeconds(5));
}
private DefaultWebTestClient(DefaultWebTestClient webTestClient, ExchangeFilterFunction filter) {
this.webClient = webTestClient.webClient.filter(filter);
this.wiretapConnector = webTestClient.wiretapConnector;
this.timeout = webTestClient.timeout;
}
private Duration getTimeout() {
return this.timeout;
@@ -134,12 +129,6 @@ class DefaultWebTestClient implements WebTestClient {
}
@Override
public WebTestClient filter(ExchangeFilterFunction filter) {
return new DefaultWebTestClient(this, filter);
}
@SuppressWarnings("unchecked")
private class DefaultUriSpec<S extends RequestHeadersSpec<?>> implements UriSpec<S> {
@@ -193,8 +182,8 @@ class DefaultWebTestClient implements WebTestClient {
}
@Override
public RequestBodySpec headers(HttpHeaders headers) {
this.bodySpec.headers(headers);
public RequestBodySpec headers(Consumer<HttpHeaders> headersConsumer) {
this.bodySpec.headers(headersConsumer);
return this;
}
@@ -229,8 +218,9 @@ class DefaultWebTestClient implements WebTestClient {
}
@Override
public RequestBodySpec cookies(MultiValueMap<String, String> cookies) {
this.bodySpec.cookies(cookies);
public RequestBodySpec cookies(
Consumer<MultiValueMap<String, String>> cookiesConsumer) {
this.bodySpec.cookies(cookiesConsumer);
return this;
}

View File

@@ -17,10 +17,15 @@
package org.springframework.test.web.reactive.server;
import java.time.Duration;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriBuilderFactory;
@@ -71,12 +76,37 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
return this;
}
@Override
public WebTestClient.Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer) {
this.webClientBuilder.defaultHeaders(headersConsumer);
return this;
}
@Override
public WebTestClient.Builder defaultCookie(String cookieName, String... cookieValues) {
this.webClientBuilder.defaultCookie(cookieName, cookieValues);
return this;
}
@Override
public WebTestClient.Builder defaultCookies(
Consumer<MultiValueMap<String, String>> cookiesConsumer) {
this.webClientBuilder.defaultCookies(cookiesConsumer);
return this;
}
@Override
public WebTestClient.Builder filter(ExchangeFilterFunction filter) {
this.webClientBuilder.filter(filter);
return this;
}
@Override
public WebTestClient.Builder filters(Consumer<List<ExchangeFilterFunction>> filtersConsumer) {
this.webClientBuilder.filters(filtersConsumer);
return this;
}
@Override
public WebTestClient.Builder exchangeStrategies(ExchangeStrategies strategies) {
this.webClientBuilder.exchangeStrategies(strategies);

View File

@@ -43,7 +43,6 @@ import org.springframework.web.reactive.config.ViewResolverRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.server.HandlerStrategies;
@@ -128,15 +127,6 @@ public interface WebTestClient {
UriSpec<RequestHeadersSpec<?>> options();
/**
* Filter the client with the given {@code ExchangeFilterFunction}.
* @param filterFunction the filter to apply to this client
* @return the filtered client
* @see ExchangeFilterFunction#apply(ExchangeFunction)
*/
WebTestClient filter(ExchangeFilterFunction filterFunction);
// Static, factory methods
/**
@@ -321,6 +311,17 @@ public interface WebTestClient {
*/
Builder defaultHeader(String headerName, String... headerValues);
/**
* Manipulate the default headers with the given consumer. The
* headers provided to the consumer are "live", so that the consumer can be used to
* {@linkplain HttpHeaders#set(String, String) overwrite} existing header values,
* {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other
* {@link HttpHeaders} methods.
* @param headersConsumer a function that consumes the {@code HttpHeaders}
* @return this builder
*/
Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer);
/**
* Add the given header to all requests that haven't added it.
* @param cookieName the cookie name
@@ -328,6 +329,32 @@ public interface WebTestClient {
*/
Builder defaultCookie(String cookieName, String... cookieValues);
/**
* Manipulate the default cookies with the given consumer. The
* map provided to the consumer is "live", so that the consumer can be used to
* {@linkplain MultiValueMap#set(Object, Object) overwrite} existing header values,
* {@linkplain MultiValueMap#remove(Object) remove} values, or use any of the other
* {@link MultiValueMap} methods.
* @param cookiesConsumer a function that consumes the cookies map
* @return this builder
*/
Builder defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
/**
* Add the given filter to the filter chain.
* @param filter the filter to be added to the chain
*/
Builder filter(ExchangeFilterFunction filter);
/**
* Manipulate the filters with the given consumer. The
* list provided to the consumer is "live", so that the consumer can be used to remove
* filters, change ordering, etc.
* @param filtersConsumer a function that consumes the filter list
* @return this builder
*/
Builder filters(Consumer<List<ExchangeFilterFunction>> filtersConsumer);
/**
* Configure the {@link ExchangeStrategies} to use.
* <p>By default {@link ExchangeStrategies#withDefaults()} is used.
@@ -417,12 +444,15 @@ public interface WebTestClient {
S cookie(String name, String value);
/**
* Copy the given cookies into the entity's cookies map.
*
* @param cookies the existing cookies to copy from
* @return the same instance
* Manipulate this request's cookies with the given consumer. The
* map provided to the consumer is "live", so that the consumer can be used to
* {@linkplain MultiValueMap#set(Object, Object) overwrite} existing header values,
* {@linkplain MultiValueMap#remove(Object) remove} values, or use any of the other
* {@link MultiValueMap} methods.
* @param cookiesConsumer a function that consumes the cookies map
* @return this builder
*/
S cookies(MultiValueMap<String, String> cookies);
S cookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
/**
* Set the value of the {@code If-Modified-Since} header.
@@ -449,11 +479,15 @@ public interface WebTestClient {
S header(String headerName, String... headerValues);
/**
* Copy the given headers into the entity's headers map.
* @param headers the existing headers to copy from
* @return the same instance
* Manipulate the request's headers with the given consumer. The
* headers provided to the consumer are "live", so that the consumer can be used to
* {@linkplain HttpHeaders#set(String, String) overwrite} existing header values,
* {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other
* {@link HttpHeaders} methods.
* @param headersConsumer a function that consumes the {@code HttpHeaders}
* @return this builder
*/
S headers(HttpHeaders headers);
S headers(Consumer<HttpHeaders> headersConsumer);
/**
* Perform the exchange without a request body.