diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java index fb9cb372694d..7023ef56459d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java @@ -100,6 +100,14 @@ public interface HandlerMapping { */ String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern"; + /** + * Name of the {@link HttpServletRequest} attribute that contains the best + * matching {@link org.springframework.web.util.pattern.PathPattern}, when + * parsed patterns are in use. + * @since 7.1 + */ + String BEST_MATCHING_PATH_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPathPattern"; + /** * Name of the boolean {@link HttpServletRequest} attribute that indicates * whether type-level mappings should be inspected. 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 0b5e366c0cb1..7005909f9770 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 @@ -171,6 +171,7 @@ private void extractMatchDetails( uriVariables = result.getUriVariables(); request.setAttribute(MATRIX_VARIABLES_ATTRIBUTE, result.getMatrixVariables()); } + request.setAttribute(BEST_MATCHING_PATH_PATTERN_ATTRIBUTE, bestPattern); request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern.getPatternString()); ServerHttpObservationFilter.findObservationContext(request) .ifPresent(context -> context.setPathPattern(bestPattern.getPatternString())); 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 d2937784e700..d81d7d488055 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 @@ -62,6 +62,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletResponse; import org.springframework.web.util.ServletRequestPathUtils; import org.springframework.web.util.UrlPathHelper; +import org.springframework.web.util.pattern.PathPattern; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -317,6 +318,21 @@ void handleMatchBestMatchingPatternAttribute(TestRequestMappingInfoHandlerMappin assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo("/{path1}/2"); } + @Test + void handleMatchBestMatchingPathPatternAttribute() { + TestRequestMappingInfoHandlerMapping mapping = new TestRequestMappingInfoHandlerMapping(); + RequestMappingInfo info = mapping.createInfo("/{path1}/2", "/**"); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/1/2"); + ServletRequestPathUtils.parseAndCache(request); + + mapping.handleMatch(info, "/1/2", request); + + assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo("/{path1}/2"); + assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATH_PATTERN_ATTRIBUTE)) + .isInstanceOfSatisfying(PathPattern.class, + pattern -> assertThat(pattern.getPatternString()).isEqualTo("/{path1}/2")); + } + @SuppressWarnings("removal") @PathPatternsParameterizedTest void handleMatchBestMatchingPatternAttributeInObservationContext(TestRequestMappingInfoHandlerMapping mapping) {