Skip to content

Commit 224f1af

Browse files
committed
Prepare to support API versioning for fn
Add default method to resolve, parse, and validate version Simplify tests
1 parent d045f44 commit 224f1af

File tree

7 files changed

+65
-56
lines changed

7 files changed

+65
-56
lines changed

spring-web/src/main/java/org/springframework/web/accept/ApiVersionStrategy.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,27 @@ void validateVersion(@Nullable Comparable<?> requestVersion, HttpServletRequest
6262
*/
6363
@Nullable Comparable<?> getDefaultVersion();
6464

65+
/**
66+
* Convenience method to return the parsed and validated request version,
67+
* or the default version if configured.
68+
* @param request the current request
69+
* @return the parsed request version, or the default version
70+
*/
71+
default @Nullable Comparable<?> resolveParseAndValidateVersion(HttpServletRequest request) {
72+
String value = resolveVersion(request);
73+
if (value == null) {
74+
return getDefaultVersion();
75+
}
76+
try {
77+
Comparable<?> version = parseVersion(value);
78+
validateVersion(version, request);
79+
return version;
80+
}
81+
catch (Exception ex) {
82+
throw new InvalidApiVersionException(value, null, ex);
83+
}
84+
}
85+
6586
/**
6687
* Check if the requested API version is deprecated, and if so handle it
6788
* accordingly, e.g. by setting response headers to signal the deprecation,

spring-webflux/src/main/java/org/springframework/web/reactive/accept/ApiVersionStrategy.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,27 @@ void validateVersion(@Nullable Comparable<?> requestVersion, ServerWebExchange e
6464
*/
6565
@Nullable Comparable<?> getDefaultVersion();
6666

67+
/**
68+
* Convenience method to return the parsed and validated request version,
69+
* or the default version if configured.
70+
* @param exchange the current exchange
71+
* @return the parsed request version, or the default version
72+
*/
73+
default @Nullable Comparable<?> resolveParseAndValidateVersion(ServerWebExchange exchange) {
74+
String value = resolveVersion(exchange);
75+
if (value == null) {
76+
return getDefaultVersion();
77+
}
78+
try {
79+
Comparable<?> version = parseVersion(value);
80+
validateVersion(version, exchange);
81+
return version;
82+
}
83+
catch (Exception ex) {
84+
throw new InvalidApiVersionException(value, null, ex);
85+
}
86+
}
87+
6788
/**
6889
* Check if the requested API version is deprecated, and if so handle it
6990
* accordingly, e.g. by setting response headers to signal the deprecation,

spring-webflux/src/main/java/org/springframework/web/reactive/accept/DefaultApiVersionStrategy.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ public DefaultApiVersionStrategy(
9393
return this.defaultVersion;
9494
}
9595

96+
/**
97+
* Whether the strategy is configured to detect supported versions.
98+
* If this is set to {@code false} then {@link #addMappedVersion} is ignored
99+
* and the list of supported versions can be built explicitly through calls
100+
* to {@link #addSupportedVersion}.
101+
*/
102+
public boolean detectSupportedVersions() {
103+
return this.detectSupportedVersions;
104+
}
105+
96106
/**
97107
* Add to the list of supported versions to check against in
98108
* {@link ApiVersionStrategy#validateVersion} before raising

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.springframework.util.CollectionUtils;
4343
import org.springframework.util.StringUtils;
4444
import org.springframework.util.StringValueResolver;
45-
import org.springframework.web.accept.InvalidApiVersionException;
4645
import org.springframework.web.bind.annotation.CrossOrigin;
4746
import org.springframework.web.bind.annotation.RequestBody;
4847
import org.springframework.web.bind.annotation.RequestMapping;
@@ -180,7 +179,7 @@ public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
180179
if (this.apiVersionStrategy != null) {
181180
Comparable<?> version = exchange.getAttribute(API_VERSION_ATTRIBUTE);
182181
if (version == null) {
183-
version = getApiVersion(exchange, this.apiVersionStrategy);
182+
version = this.apiVersionStrategy.resolveParseAndValidateVersion(exchange);
184183
if (version != null) {
185184
exchange.getAttributes().put(API_VERSION_ATTRIBUTE, version);
186185
}
@@ -189,21 +188,6 @@ public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
189188
return super.getHandlerInternal(exchange);
190189
}
191190

192-
private static @Nullable Comparable<?> getApiVersion(ServerWebExchange exchange, ApiVersionStrategy strategy) {
193-
String value = strategy.resolveVersion(exchange);
194-
if (value == null) {
195-
return strategy.getDefaultVersion();
196-
}
197-
try {
198-
Comparable<?> version = strategy.parseVersion(value);
199-
strategy.validateVersion(version, exchange);
200-
return version;
201-
}
202-
catch (Exception ex) {
203-
throw new InvalidApiVersionException(value, null, ex);
204-
}
205-
}
206-
207191
/**
208192
* Uses type-level and method-level {@link RequestMapping @RequestMapping}
209193
* and {@link HttpExchange @HttpExchange} annotations to create the

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingVersionIntegrationTests.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,24 @@ protected ApplicationContext initApplicationContext() {
5050

5151

5252
@ParameterizedHttpServerTest
53-
void initialVersion(HttpServer httpServer) throws Exception {
53+
void mapVersion(HttpServer httpServer) throws Exception {
5454
startServer(httpServer);
55+
5556
assertThat(exchangeWithVersion("1.0").getBody()).isEqualTo("none");
5657
assertThat(exchangeWithVersion("1.1").getBody()).isEqualTo("none");
57-
}
58-
59-
@ParameterizedHttpServerTest
60-
void baselineVersion(HttpServer httpServer) throws Exception {
61-
startServer(httpServer);
6258
assertThat(exchangeWithVersion("1.2").getBody()).isEqualTo("1.2");
6359
assertThat(exchangeWithVersion("1.3").getBody()).isEqualTo("1.2");
64-
}
65-
66-
@ParameterizedHttpServerTest
67-
void fixedVersion(HttpServer httpServer) throws Exception {
68-
startServer(httpServer);
6960
assertThat(exchangeWithVersion("1.5").getBody()).isEqualTo("1.5");
70-
assertThatThrownBy(() -> exchangeWithVersion("1.6")).isInstanceOf(HttpClientErrorException.BadRequest.class);
61+
62+
assertThatThrownBy(() -> exchangeWithVersion("1.6"))
63+
.as("Should reject if highest supported below request version is fixed")
64+
.isInstanceOf(HttpClientErrorException.BadRequest.class);
7165
}
7266

7367
@ParameterizedHttpServerTest
7468
void deprecation(HttpServer httpServer) throws Exception {
7569
startServer(httpServer);
70+
7671
assertThat(exchangeWithVersion("1").getHeaders().getFirst("Link"))
7772
.isEqualTo("<https://example.org/deprecation>; rel=\"deprecation\"; type=\"text/html\"");
7873
}

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import org.springframework.web.accept.ApiVersionStrategy;
4747
import org.springframework.web.accept.ContentNegotiationManager;
4848
import org.springframework.web.accept.DefaultApiVersionStrategy;
49-
import org.springframework.web.accept.InvalidApiVersionException;
5049
import org.springframework.web.bind.annotation.CrossOrigin;
5150
import org.springframework.web.bind.annotation.RequestBody;
5251
import org.springframework.web.bind.annotation.RequestMapping;
@@ -207,7 +206,7 @@ protected boolean isHandler(Class<?> beanType) {
207206
if (this.apiVersionStrategy != null) {
208207
Comparable<?> version = (Comparable<?>) request.getAttribute(API_VERSION_ATTRIBUTE);
209208
if (version == null) {
210-
version = getApiVersion(request, this.apiVersionStrategy);
209+
version = this.apiVersionStrategy.resolveParseAndValidateVersion(request);
211210
if (version != null) {
212211
request.setAttribute(API_VERSION_ATTRIBUTE, version);
213212
}
@@ -216,21 +215,6 @@ protected boolean isHandler(Class<?> beanType) {
216215
return super.getHandlerInternal(request);
217216
}
218217

219-
private static @Nullable Comparable<?> getApiVersion(HttpServletRequest request, ApiVersionStrategy strategy) {
220-
String value = strategy.resolveVersion(request);
221-
if (value == null) {
222-
return strategy.getDefaultVersion();
223-
}
224-
try {
225-
Comparable<?> version = strategy.parseVersion(value);
226-
strategy.validateVersion(version, request);
227-
return version;
228-
}
229-
catch (Exception ex) {
230-
throw new InvalidApiVersionException(value, null, ex);
231-
}
232-
}
233-
234218
/**
235219
* Uses type-level and method-level {@link RequestMapping @RequestMapping}
236220
* and {@link HttpExchange @HttpExchange} annotations to create the

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingVersionHandlerMethodTests.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,17 @@ void setUp() throws ServletException {
5959

6060

6161
@Test
62-
void initialVersion() throws Exception {
62+
void mapVersion() throws Exception {
6363
assertThat(requestWithVersion("1.0").getContentAsString()).isEqualTo("none");
6464
assertThat(requestWithVersion("1.1").getContentAsString()).isEqualTo("none");
65-
}
66-
67-
@Test
68-
void baselineVersion() throws Exception {
6965
assertThat(requestWithVersion("1.2").getContentAsString()).isEqualTo("1.2");
7066
assertThat(requestWithVersion("1.3").getContentAsString()).isEqualTo("1.2");
71-
}
72-
73-
@Test
74-
void fixedVersion() throws Exception {
7567
assertThat(requestWithVersion("1.5").getContentAsString()).isEqualTo("1.5");
7668

7769
MockHttpServletResponse response = requestWithVersion("1.6");
78-
assertThat(response.getStatus()).isEqualTo(400);
70+
assertThat(response.getStatus())
71+
.as("Should reject if highest supported below request version is fixed")
72+
.isEqualTo(400);
7973
}
8074

8175
@Test

0 commit comments

Comments
 (0)