mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
WebTestClient support for API versioning
Closes gh-34568
This commit is contained in:
+25
-3
@@ -56,6 +56,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.ApiVersionInserter;
|
||||
import org.springframework.web.reactive.function.BodyInserter;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
@@ -88,6 +89,8 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
|
||||
private final @Nullable MultiValueMap<String, String> defaultCookies;
|
||||
|
||||
private final @Nullable ApiVersionInserter apiVersionInserter;
|
||||
|
||||
private final Consumer<EntityExchangeResult<?>> entityResultConsumer;
|
||||
|
||||
private final Duration responseTimeout;
|
||||
@@ -97,10 +100,11 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
private final AtomicLong requestIndex = new AtomicLong();
|
||||
|
||||
|
||||
DefaultWebTestClient(ClientHttpConnector connector, ExchangeStrategies exchangeStrategies,
|
||||
DefaultWebTestClient(
|
||||
ClientHttpConnector connector, ExchangeStrategies exchangeStrategies,
|
||||
Function<ClientHttpConnector, ExchangeFunction> exchangeFactory, UriBuilderFactory uriBuilderFactory,
|
||||
@Nullable HttpHeaders headers, @Nullable MultiValueMap<String, String> cookies,
|
||||
Consumer<EntityExchangeResult<?>> entityResultConsumer,
|
||||
@Nullable ApiVersionInserter apiVersionInserter, Consumer<EntityExchangeResult<?>> entityResultConsumer,
|
||||
@Nullable Duration responseTimeout, DefaultWebTestClientBuilder clientBuilder) {
|
||||
|
||||
this.wiretapConnector = new WiretapConnector(connector);
|
||||
@@ -110,6 +114,7 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
this.uriBuilderFactory = uriBuilderFactory;
|
||||
this.defaultHeaders = headers;
|
||||
this.defaultCookies = cookies;
|
||||
this.apiVersionInserter = apiVersionInserter;
|
||||
this.entityResultConsumer = entityResultConsumer;
|
||||
this.responseTimeout = (responseTimeout != null ? responseTimeout : Duration.ofSeconds(5));
|
||||
this.builder = clientBuilder;
|
||||
@@ -186,6 +191,8 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
|
||||
private @Nullable MultiValueMap<String, String> cookies;
|
||||
|
||||
private @Nullable Object apiVersion;
|
||||
|
||||
private @Nullable BodyInserter<?, ? super ClientHttpRequest> inserter;
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<>(4);
|
||||
@@ -310,6 +317,12 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBodySpec apiVersion(Object version) {
|
||||
this.apiVersion = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestHeadersSpec<?> bodyValue(Object body) {
|
||||
this.inserter = BodyInserters.fromValue(body);
|
||||
@@ -373,6 +386,10 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
if (!this.headers.isEmpty()) {
|
||||
headersToUse.putAll(this.headers);
|
||||
}
|
||||
if (this.apiVersion != null) {
|
||||
Assert.state(apiVersionInserter != null, "No ApiVersionInserter configured");
|
||||
apiVersionInserter.insertVersion(this.apiVersion, headersToUse);
|
||||
}
|
||||
})
|
||||
.cookies(cookiesToUse -> {
|
||||
if (!CollectionUtils.isEmpty(DefaultWebTestClient.this.defaultCookies)) {
|
||||
@@ -386,7 +403,12 @@ class DefaultWebTestClient implements WebTestClient {
|
||||
}
|
||||
|
||||
private URI initUri() {
|
||||
return (this.uri != null ? this.uri : DefaultWebTestClient.this.uriBuilderFactory.expand(""));
|
||||
URI uriToUse = this.uri != null ? this.uri : DefaultWebTestClient.this.uriBuilderFactory.expand("");
|
||||
if (this.apiVersion != null) {
|
||||
Assert.state(apiVersionInserter != null, "No ApiVersionInserter configured");
|
||||
uriToUse = apiVersionInserter.insertVersion(this.apiVersion, uriToUse);
|
||||
}
|
||||
return uriToUse;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-4
@@ -37,6 +37,7 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.ApiVersionInserter;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunctions;
|
||||
@@ -85,6 +86,8 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||
|
||||
private @Nullable MultiValueMap<String, String> defaultCookies;
|
||||
|
||||
private @Nullable ApiVersionInserter apiVersionInserter;
|
||||
|
||||
private @Nullable List<ExchangeFilterFunction> filters;
|
||||
|
||||
private Consumer<EntityExchangeResult<?>> entityResultConsumer = result -> {};
|
||||
@@ -142,6 +145,7 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||
}
|
||||
this.defaultCookies = (other.defaultCookies != null ?
|
||||
new LinkedMultiValueMap<>(other.defaultCookies) : null);
|
||||
this.apiVersionInserter = other.apiVersionInserter;
|
||||
this.filters = (other.filters != null ? new ArrayList<>(other.filters) : null);
|
||||
this.entityResultConsumer = other.entityResultConsumer;
|
||||
this.strategies = other.strategies;
|
||||
@@ -200,6 +204,12 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||
return this.defaultCookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebTestClient.Builder apiVersionInserter(ApiVersionInserter apiVersionInserter) {
|
||||
this.apiVersionInserter = apiVersionInserter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebTestClient.Builder filter(ExchangeFilterFunction filter) {
|
||||
Assert.notNull(filter, "ExchangeFilterFunction is required");
|
||||
@@ -283,10 +293,12 @@ class DefaultWebTestClientBuilder implements WebTestClient.Builder {
|
||||
.orElse(exchange);
|
||||
|
||||
};
|
||||
return new DefaultWebTestClient(connectorToUse, exchangeStrategies, exchangeFactory, initUriBuilderFactory(),
|
||||
this.defaultHeaders != null ? HttpHeaders.readOnlyHttpHeaders(this.defaultHeaders) : null,
|
||||
this.defaultCookies != null ? CollectionUtils.unmodifiableMultiValueMap(this.defaultCookies) : null,
|
||||
this.entityResultConsumer, this.responseTimeout, new DefaultWebTestClientBuilder(this));
|
||||
return new DefaultWebTestClient(
|
||||
connectorToUse, exchangeStrategies, exchangeFactory, initUriBuilderFactory(),
|
||||
(this.defaultHeaders != null ? HttpHeaders.readOnlyHttpHeaders(this.defaultHeaders) : null),
|
||||
(this.defaultCookies != null ? CollectionUtils.unmodifiableMultiValueMap(this.defaultCookies) : null),
|
||||
this.apiVersionInserter, this.entityResultConsumer,
|
||||
this.responseTimeout, new DefaultWebTestClientBuilder(this));
|
||||
}
|
||||
|
||||
private static ClientHttpConnector initConnector() {
|
||||
|
||||
+22
@@ -45,6 +45,8 @@ import org.springframework.test.json.JsonCompareMode;
|
||||
import org.springframework.test.json.JsonComparison;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.client.ApiVersionFormatter;
|
||||
import org.springframework.web.client.ApiVersionInserter;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.reactive.config.BlockingExecutionConfigurer;
|
||||
import org.springframework.web.reactive.config.CorsRegistry;
|
||||
@@ -428,6 +430,15 @@ public interface WebTestClient {
|
||||
*/
|
||||
Builder defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
|
||||
|
||||
/**
|
||||
* Configure an {@link ApiVersionInserter} to abstract how an API version
|
||||
* specified via {@link RequestHeadersSpec#apiVersion(Object)}
|
||||
* is inserted into the request.
|
||||
* @param apiVersionInserter the inserter to use
|
||||
* @since 7.0
|
||||
*/
|
||||
Builder apiVersionInserter(ApiVersionInserter apiVersionInserter);
|
||||
|
||||
/**
|
||||
* Add the given filter to the filter chain.
|
||||
* @param filter the filter to be added to the chain
|
||||
@@ -643,6 +654,17 @@ public interface WebTestClient {
|
||||
*/
|
||||
S headers(Consumer<HttpHeaders> headersConsumer);
|
||||
|
||||
/**
|
||||
* Set an API version for the request. The version is inserted into the
|
||||
* request by the {@link Builder#apiVersionInserter(ApiVersionInserter)
|
||||
* configured} {@code ApiVersionInserter}.
|
||||
* @param version the API version of the request; this can be a String or
|
||||
* some Object that can be formatted the inserter, e.g. through an
|
||||
* {@link ApiVersionFormatter}.
|
||||
* @since 7.0
|
||||
*/
|
||||
S apiVersion(Object version);
|
||||
|
||||
/**
|
||||
* Set the attribute with the given name to the given value.
|
||||
* @param name the name of the attribute to add
|
||||
|
||||
Reference in New Issue
Block a user