Add defaultApiVersion to RestClient and WebClient

Closes gh-34857
This commit is contained in:
rstoyanchev
2025-05-05 19:05:39 +01:00
parent fef969145d
commit 22e7f24731
8 changed files with 192 additions and 15 deletions

View File

@@ -108,6 +108,8 @@ final class DefaultRestClient implements RestClient {
private final @Nullable MultiValueMap<String, String> defaultCookies;
private final @Nullable Object defaultApiVersion;
private final @Nullable ApiVersionInserter apiVersionInserter;
private final @Nullable Consumer<RequestHeadersSpec<?>> defaultRequest;
@@ -130,7 +132,7 @@ final class DefaultRestClient implements RestClient {
UriBuilderFactory uriBuilderFactory,
@Nullable HttpHeaders defaultHeaders,
@Nullable MultiValueMap<String, String> defaultCookies,
@Nullable ApiVersionInserter apiVersionInserter,
@Nullable Object defaultApiVersion, @Nullable ApiVersionInserter apiVersionInserter,
@Nullable Consumer<RequestHeadersSpec<?>> defaultRequest,
@Nullable List<StatusHandler> statusHandlers,
List<HttpMessageConverter<?>> messageConverters,
@@ -145,6 +147,7 @@ final class DefaultRestClient implements RestClient {
this.uriBuilderFactory = uriBuilderFactory;
this.defaultHeaders = defaultHeaders;
this.defaultCookies = defaultCookies;
this.defaultApiVersion = defaultApiVersion;
this.apiVersionInserter = apiVersionInserter;
this.defaultRequest = defaultRequest;
this.defaultStatusHandlers = (statusHandlers != null ? new ArrayList<>(statusHandlers) : new ArrayList<>());
@@ -609,13 +612,18 @@ final class DefaultRestClient implements RestClient {
private URI initUri() {
URI uriToUse = this.uri != null ? this.uri : DefaultRestClient.this.uriBuilderFactory.expand("");
if (this.apiVersion != null) {
Object version = getApiVersionOrDefault();
if (version != null) {
Assert.state(apiVersionInserter != null, "No ApiVersionInserter configured");
uriToUse = apiVersionInserter.insertVersion(this.apiVersion, uriToUse);
uriToUse = apiVersionInserter.insertVersion(version, uriToUse);
}
return uriToUse;
}
private @Nullable Object getApiVersionOrDefault() {
return (this.apiVersion != null ? this.apiVersion : DefaultRestClient.this.defaultApiVersion);
}
private @Nullable String serializeCookies() {
MultiValueMap<String, String> map;
MultiValueMap<String, String> defaultCookies = DefaultRestClient.this.defaultCookies;
@@ -652,7 +660,8 @@ final class DefaultRestClient implements RestClient {
private @Nullable HttpHeaders initHeaders() {
HttpHeaders defaultHeaders = DefaultRestClient.this.defaultHeaders;
if (this.apiVersion == null) {
Object version = getApiVersionOrDefault();
if (version == null) {
if (this.headers == null || this.headers.isEmpty()) {
return defaultHeaders;
}
@@ -669,9 +678,9 @@ final class DefaultRestClient implements RestClient {
result.putAll(this.headers);
}
if (this.apiVersion != null) {
if (version != null) {
Assert.state(apiVersionInserter != null, "No ApiVersionInserter configured");
apiVersionInserter.insertVersion(this.apiVersion, result);
apiVersionInserter.insertVersion(version, result);
}
return result;

View File

@@ -116,7 +116,6 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
private static final boolean kotlinSerializationProtobufPresent;
static {
ClassLoader loader = DefaultRestClientBuilder.class.getClassLoader();
@@ -150,6 +149,8 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
private @Nullable MultiValueMap<String, String> defaultCookies;
private @Nullable Object defaultApiVersion;
private @Nullable ApiVersionInserter apiVersionInserter;
private @Nullable Consumer<RestClient.RequestHeadersSpec<?>> defaultRequest;
@@ -188,6 +189,7 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
this.defaultHeaders = null;
}
this.defaultCookies = (other.defaultCookies != null ? new LinkedMultiValueMap<>(other.defaultCookies) : null);
this.defaultApiVersion = other.defaultApiVersion;
this.apiVersionInserter = other.apiVersionInserter;
this.defaultRequest = other.defaultRequest;
this.statusHandlers = (other.statusHandlers != null ? new ArrayList<>(other.statusHandlers) : null);
@@ -324,6 +326,12 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
return this.defaultCookies;
}
@Override
public RestClient.Builder defaultApiVersion(@Nullable Object version) {
this.defaultApiVersion = version;
return this;
}
@Override
public RestClient.Builder apiVersionInserter(ApiVersionInserter apiVersionInserter) {
this.apiVersionInserter = apiVersionInserter;
@@ -521,7 +529,7 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
return new DefaultRestClient(
requestFactory, this.interceptors, this.bufferingPredicate, this.initializers,
uriBuilderFactory, defaultHeaders, defaultCookies,
uriBuilderFactory, defaultHeaders, defaultCookies, this.defaultApiVersion,
this.apiVersionInserter, this.defaultRequest,
this.statusHandlers, converters,
this.observationRegistry, this.observationConvention,

View File

@@ -332,6 +332,15 @@ public interface RestClient {
*/
Builder defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer);
/**
* Global option to specify an API version to be added to every request,
* if not explicitly set.
* @param version the version to use
* @return this builder
* @since 7.0
*/
Builder defaultApiVersion(Object version);
/**
* Configure an {@link ApiVersionInserter} to abstract how an API version
* specified via {@link RequestHeadersSpec#apiVersion(Object)}

View File

@@ -86,7 +86,16 @@ public class RestClientVersionTests {
assertThatIllegalStateException()
.isThrownBy(() -> performRequest(DefaultApiVersionInserter.fromPathSegment(2)))
.withMessage("Cannot insert version into '/path' at path segment index 2");
}
}
@Test
void defaultVersion() {
ApiVersionInserter inserter = DefaultApiVersionInserter.fromHeader("X-API-Version").build();
RestClient restClient = restClientBuilder.defaultApiVersion(1.2).apiVersionInserter(inserter).build();
restClient.get().uri("/path").retrieve().body(String.class);
expectRequest(request -> assertThat(request.getHeader("X-API-Version")).isEqualTo("1.2"));
}
private void performRequest(DefaultApiVersionInserter.Builder builder) {
ApiVersionInserter versionInserter = builder.build();