diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java index 96a581279b..282918f69f 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java @@ -50,7 +50,7 @@ import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.HandlerResult; -import org.springframework.web.reactive.result.method.RequestMappingInfo.BuilderConfiguration; +import org.springframework.web.reactive.result.method.RequestMappingInfo.*; import org.springframework.web.server.MethodNotAllowedException; import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; @@ -58,25 +58,14 @@ import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.util.pattern.PathPattern; -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get; -import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.method; -import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.post; -import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.put; -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.HEAD; -import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS; -import static org.springframework.web.method.MvcAnnotationPredicates.getMapping; -import static org.springframework.web.method.MvcAnnotationPredicates.requestMapping; -import static org.springframework.web.method.ResolvableMethod.on; -import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE; -import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE; -import static org.springframework.web.reactive.result.method.RequestMappingInfo.paths; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.*; +import static org.springframework.web.bind.annotation.RequestMethod.*; +import static org.springframework.web.method.MvcAnnotationPredicates.*; +import static org.springframework.web.method.ResolvableMethod.*; +import static org.springframework.web.reactive.HandlerMapping.*; +import static org.springframework.web.reactive.result.method.RequestMappingInfo.*; /** * Unit tests for {@link RequestMappingInfoHandlerMapping}. @@ -287,6 +276,18 @@ public class RequestMappingInfoHandlerMappingTests { assertEquals(Arrays.asList("red", "blue", "green"), matrixVariables.get("colors")); assertEquals("2012", matrixVariables.getFirst("year")); assertEquals("cars", uriVariables.get("cars")); + + // SPR-11897 + exchange = MockServerWebExchange.from(get("/a=42;b=c")); + handleMatch(exchange, "/{foo}"); + + matrixVariables = getMatrixVariables(exchange, "foo"); + uriVariables = getUriTemplateVariables(exchange); + + assertNotNull(matrixVariables); + assertEquals(1, matrixVariables.size()); + assertEquals("c", matrixVariables.getFirst("b")); + assertEquals("a=42", uriVariables.get("foo")); } @Test diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java index 3544566145..98722eab55 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java @@ -149,20 +149,23 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe Map> result = new LinkedHashMap<>(); uriVariables.forEach((uriVarKey, uriVarValue) -> { + int equalsIndex = uriVarValue.indexOf('='); if (equalsIndex == -1) { return; } - String matrixVariables; - int semicolonIndex = uriVarValue.indexOf(';'); - if ((semicolonIndex == -1) || (semicolonIndex == 0) || (equalsIndex < semicolonIndex)) { + if (semicolonIndex != -1 && semicolonIndex != 0) { + uriVariables.put(uriVarKey, uriVarValue.substring(0, semicolonIndex)); + } + + String matrixVariables; + if (semicolonIndex == -1 || semicolonIndex == 0 || equalsIndex < semicolonIndex) { matrixVariables = uriVarValue; } else { matrixVariables = uriVarValue.substring(semicolonIndex + 1); - uriVariables.put(uriVarKey, uriVarValue.substring(0, semicolonIndex)); } MultiValueMap vars = WebUtils.parseMatrixVariables(matrixVariables); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java index 4f6ae1a1be..68bae95edb 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java @@ -311,6 +311,7 @@ public class RequestMappingInfoHandlerMappingTests { MultiValueMap matrixVariables; Map uriVariables; + // URI var parsed into path variable + matrix params.. request = new MockHttpServletRequest(); handleMatch(request, "/{cars}", "/cars;colors=red,blue,green;year=2012"); @@ -322,6 +323,7 @@ public class RequestMappingInfoHandlerMappingTests { assertEquals("2012", matrixVariables.getFirst("year")); assertEquals("cars", uriVariables.get("cars")); + // URI var with regex for path variable, and URI var for matrix params.. request = new MockHttpServletRequest(); handleMatch(request, "/{cars:[^;]+}{params}", "/cars;colors=red,blue,green;year=2012"); @@ -334,6 +336,7 @@ public class RequestMappingInfoHandlerMappingTests { assertEquals("cars", uriVariables.get("cars")); assertEquals(";colors=red,blue,green;year=2012", uriVariables.get("params")); + // URI var with regex for path variable, and (empty) URI var for matrix params.. request = new MockHttpServletRequest(); handleMatch(request, "/{cars:[^;]+}{params}", "/cars"); @@ -343,6 +346,18 @@ public class RequestMappingInfoHandlerMappingTests { assertNull(matrixVariables); assertEquals("cars", uriVariables.get("cars")); assertEquals("", uriVariables.get("params")); + + // SPR-11897 + request = new MockHttpServletRequest(); + handleMatch(request, "/{foo}", "/a=42;b=c"); + + matrixVariables = getMatrixVariables(request, "foo"); + uriVariables = getUriTemplateVariables(request); + + assertNotNull(matrixVariables); + assertEquals("42", matrixVariables.getFirst("a")); + assertEquals("c", matrixVariables.getFirst("b")); + assertEquals("a=42", uriVariables.get("foo")); } @Test // SPR-10140, SPR-16867