Skip to content

Commit e3d3272

Browse files
committed
Map version from @HttpExchange to RequestMappingInfo
The version attribute from @HttpExchange and its shortcut annotations such as @GetExchange was not passed to the RequestMappingInfo builder, which caused version-based routing to be silently ignored for controllers annotated with @HttpExchange. This commit adds .version(httpExchange.version()) to the createRequestMappingInfo(HttpExchange, ...) method in both WebMvc and WebFlux RequestMappingHandlerMapping, and adds corresponding tests. Signed-off-by: Renato Mameli <renatomamel410@gmail.com>
1 parent 2ee4c3a commit e3d3272

File tree

4 files changed

+73
-6
lines changed

4 files changed

+73
-6
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ protected RequestMappingInfo createRequestMappingInfo(
373373
.methods(toMethodArray(httpExchange.method()))
374374
.consumes(toStringArray(httpExchange.contentType()))
375375
.produces(httpExchange.accept())
376-
.headers(httpExchange.headers());
376+
.headers(httpExchange.headers())
377+
.version(httpExchange.version());
377378

378379
if (customCondition != null) {
379380
builder.customCondition(customCondition);

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.springframework.web.reactive.result.condition.MediaTypeExpression;
5959
import org.springframework.web.reactive.result.method.RequestMappingInfo;
6060
import org.springframework.web.server.ServerWebExchange;
61+
import org.springframework.web.service.annotation.GetExchange;
6162
import org.springframework.web.service.annotation.HttpExchange;
6263
import org.springframework.web.service.annotation.PostExchange;
6364
import org.springframework.web.service.annotation.PutExchange;
@@ -130,6 +131,34 @@ void versionInvalid() {
130131
.verifyError(InvalidApiVersionException.class);
131132
}
132133

134+
@Test
135+
void httpExchangeWithVersion() {
136+
DefaultApiVersionStrategy versionStrategy = new DefaultApiVersionStrategy(
137+
List.of(new HeaderApiVersionResolver("API-Version")), new SemanticApiVersionParser(),
138+
true, null, true, null, null);
139+
this.handlerMapping.setApiVersionStrategy(versionStrategy);
140+
this.handlerMapping.afterPropertiesSet();
141+
142+
Class<HttpExchangeController> clazz = HttpExchangeController.class;
143+
Method method = ReflectionUtils.findMethod(clazz, "versionedExchange");
144+
RequestMappingInfo mappingInfo = this.handlerMapping.getMappingForMethod(method, clazz);
145+
146+
assertThat(mappingInfo).isNotNull();
147+
assertThat(mappingInfo.getVersionCondition().getVersion()).isEqualTo("1.1");
148+
}
149+
150+
@Test
151+
void httpExchangeWithoutVersionHasNoVersionCondition() {
152+
this.handlerMapping.afterPropertiesSet();
153+
154+
Class<HttpExchangeController> clazz = HttpExchangeController.class;
155+
Method method = ReflectionUtils.findMethod(clazz, "defaultValuesExchange");
156+
RequestMappingInfo mappingInfo = this.handlerMapping.getMappingForMethod(method, clazz);
157+
158+
assertThat(mappingInfo).isNotNull();
159+
assertThat(mappingInfo.getVersionCondition().getVersion()).isNull();
160+
}
161+
133162
private ServerWebExchange initExchangeForVersionTest(String version) {
134163

135164
((StaticWebApplicationContext) this.handlerMapping.getApplicationContext())
@@ -640,6 +669,11 @@ public void customValuesExchange(){}
640669
public String customHeadersExchange() {
641670
return "info";
642671
}
672+
673+
@GetExchange(version = "1.1")
674+
public String versionedExchange() {
675+
return "v1.1";
676+
}
643677
}
644678

645679
@HttpExchange("/exchange")

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@ protected RequestMappingInfo createRequestMappingInfo(
400400
.methods(toMethodArray(httpExchange.method()))
401401
.consumes(toStringArray(httpExchange.contentType()))
402402
.produces(httpExchange.accept())
403-
.headers(httpExchange.headers());
403+
.headers(httpExchange.headers())
404+
.version(httpExchange.version());
404405

405406
if (customCondition != null) {
406407
builder.customCondition(customCondition);

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

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.springframework.web.context.support.StaticWebApplicationContext;
5252
import org.springframework.web.method.HandlerMethod;
5353
import org.springframework.web.method.HandlerTypePredicate;
54+
import org.springframework.web.service.annotation.GetExchange;
5455
import org.springframework.web.service.annotation.HttpExchange;
5556
import org.springframework.web.service.annotation.PostExchange;
5657
import org.springframework.web.service.annotation.PutExchange;
@@ -169,22 +170,36 @@ private void initRequestPath(RequestMappingHandlerMapping mapping, MockHttpServl
169170

170171
@PathPatternsParameterizedTest
171172
void version(RequestMappingHandlerMapping mapping) throws Exception {
172-
MockHttpServletRequest request = initRequestForVersionTest(mapping, "1.1");
173+
MockHttpServletRequest request = initRequestForVersionTest(mapping, VersionController.class, "1.1");
173174
HandlerMethod handlerMethod = (HandlerMethod) mapping.getHandler(request).getHandler();
174175
assertThat(handlerMethod.getMethod().getName()).isEqualTo("foo1_1");
175176
}
176177

177178
@PathPatternsParameterizedTest
178179
void versionInvalid(RequestMappingHandlerMapping mapping) throws Exception {
179-
MockHttpServletRequest request = initRequestForVersionTest(mapping, "99");
180+
MockHttpServletRequest request = initRequestForVersionTest(mapping, VersionController.class, "99");
180181
assertThatThrownBy(() -> mapping.getHandler(request)).isInstanceOf(InvalidApiVersionException.class);
181182
}
182183

184+
@PathPatternsParameterizedTest
185+
void versionWithHttpExchange(RequestMappingHandlerMapping mapping) throws Exception {
186+
MockHttpServletRequest request = initRequestForVersionTest(mapping, VersionHttpExchangeController.class, "1.1");
187+
HandlerMethod handlerMethod = (HandlerMethod) mapping.getHandler(request).getHandler();
188+
assertThat(handlerMethod.getMethod().getName()).isEqualTo("foo1_1");
189+
}
190+
191+
@PathPatternsParameterizedTest
192+
void versionInvalidWithHttpExchange(RequestMappingHandlerMapping mapping) {
193+
MockHttpServletRequest request = initRequestForVersionTest(mapping, VersionHttpExchangeController.class, "99");
194+
assertThatThrownBy(() -> mapping.getHandler(request)).isInstanceOf(InvalidApiVersionException.class);
195+
}
196+
197+
183198
private static MockHttpServletRequest initRequestForVersionTest(
184-
RequestMappingHandlerMapping mapping, String version) {
199+
RequestMappingHandlerMapping mapping, Class<?> controllerClass, String version) {
185200

186201
((StaticWebApplicationContext) mapping.getApplicationContext())
187-
.registerSingleton("controller", VersionController.class);
202+
.registerSingleton("controller", controllerClass);
188203

189204
DefaultApiVersionStrategy versionStrategy = new DefaultApiVersionStrategy(
190205
List.of(new HeaderApiVersionResolver("API-Version")), new SemanticApiVersionParser(),
@@ -679,6 +694,22 @@ public String foo1_1() {
679694
}
680695

681696

697+
@RestController
698+
@HttpExchange("/foo")
699+
static class VersionHttpExchangeController {
700+
701+
@GetExchange
702+
public String foo() {
703+
return "foo";
704+
}
705+
706+
@GetExchange(version = "1.1")
707+
public String foo1_1() {
708+
return "foo1_1";
709+
}
710+
}
711+
712+
682713
@RestController
683714
@HttpExchange("/exchange")
684715
static class HttpExchangeController {

0 commit comments

Comments
 (0)