mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-29 02:39:04 +00:00
Polishing contribution
See gh-37272
This commit is contained in:
+1
@@ -221,6 +221,7 @@ public class RouterFunctionMapping extends AbstractHandlerMapping implements Ini
|
||||
if (matchingPattern != null) {
|
||||
servletRequest.removeAttribute(RouterFunctions.MATCHING_PATTERN_ATTRIBUTE);
|
||||
servletRequest.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, matchingPattern.getPatternString());
|
||||
servletRequest.setAttribute(BEST_MATCHING_PATH_PATTERN_ATTRIBUTE, matchingPattern);
|
||||
ServerHttpObservationFilter.findObservationContext(request.servletRequest())
|
||||
.ifPresent(context -> context.setPathPattern(matchingPattern.getPatternString()));
|
||||
}
|
||||
|
||||
+63
-4
@@ -319,7 +319,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
pathWithinMapping = UrlPathHelper.defaultInstance.removeSemicolonContent(pathWithinMapping);
|
||||
PathPattern.PathMatchInfo pathMatchInfo = pattern.matchAndExtract(path);
|
||||
Map<String, String> uriVariables = (pathMatchInfo != null ? pathMatchInfo.getUriVariables(): null);
|
||||
return buildPathExposingHandler(handler, pattern.getPatternString(), pathWithinMapping, uriVariables);
|
||||
return buildPathExposingHandler(handler, pattern, pathWithinMapping, uriVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,12 +419,14 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
/**
|
||||
* Build a handler object for the given raw handler, exposing the actual
|
||||
* handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}, as well as
|
||||
* handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE},
|
||||
* the {@link #BEST_MATCHING_PATTERN_ATTRIBUTE}, as well as
|
||||
* the {@link #URI_TEMPLATE_VARIABLES_ATTRIBUTE} before executing the handler.
|
||||
* <p>The default implementation builds a {@link HandlerExecutionChain}
|
||||
* with a special interceptor that exposes the path attribute and URI
|
||||
* template variables
|
||||
* @param rawHandler the raw handler to expose
|
||||
* @param bestMatchingPattern the {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern}
|
||||
* @param pathWithinMapping the path to expose before executing the handler
|
||||
* @param uriTemplateVariables the URI template variables, can be {@code null} if no variables found
|
||||
* @return the final handler object
|
||||
@@ -440,8 +442,33 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
return chain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a handler object for the given raw handler, exposing the actual
|
||||
* handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE},
|
||||
* the {@link #BEST_MATCHING_PATH_PATTERN_ATTRIBUTE}
|
||||
* the {@link #BEST_MATCHING_PATTERN_ATTRIBUTE}, as well as
|
||||
* the {@link #URI_TEMPLATE_VARIABLES_ATTRIBUTE} before executing the handler.
|
||||
* @param rawHandler the raw handler to expose
|
||||
* @param bestMatchingPattern the {@linkplain HandlerMapping#BEST_MATCHING_PATH_PATTERN_ATTRIBUTE best matching pattern}
|
||||
* @param pathWithinMapping the path to expose before executing the handler
|
||||
* @param uriTemplateVariables the URI template variables, can be {@code null} if no variables found
|
||||
* @return the final handler object
|
||||
* @since 7.1
|
||||
*/
|
||||
protected Object buildPathExposingHandler(Object rawHandler, PathPattern bestMatchingPattern,
|
||||
String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {
|
||||
|
||||
HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
|
||||
chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
|
||||
if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
|
||||
chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the path within the current mapping as request attribute.
|
||||
* @param bestMatchingPattern the best matching pattern
|
||||
* @param pathWithinMapping the path within the current mapping
|
||||
* @param request the request to expose the path to
|
||||
* @see #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
|
||||
@@ -455,6 +482,22 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
request.setAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the path within the current mapping as request attribute.
|
||||
* @param bestMatchingPattern the best matching pattern
|
||||
* @param pathWithinMapping the path within the current mapping
|
||||
* @param request the request to expose the path to
|
||||
* @since 7.1
|
||||
* @see #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
|
||||
* @see #BEST_MATCHING_PATH_PATTERN_ATTRIBUTE
|
||||
*/
|
||||
protected void exposePathWithinMapping(PathPattern bestMatchingPattern, String pathWithinMapping,
|
||||
HttpServletRequest request) {
|
||||
|
||||
request.setAttribute(BEST_MATCHING_PATH_PATTERN_ATTRIBUTE, bestMatchingPattern);
|
||||
exposePathWithinMapping(bestMatchingPattern.getPatternString(), pathWithinMapping, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the URI templates variables as request attribute.
|
||||
* @param uriTemplateVariables the URI template variables
|
||||
@@ -495,23 +538,39 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
/**
|
||||
* Special interceptor for exposing the
|
||||
* {@link AbstractUrlHandlerMapping#PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE} attribute.
|
||||
* {@link AbstractUrlHandlerMapping#PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE} and,
|
||||
* when parsed patterns are in use, the
|
||||
* {@link AbstractUrlHandlerMapping#BEST_MATCHING_PATH_PATTERN_ATTRIBUTE} attribute.
|
||||
* @see AbstractUrlHandlerMapping#exposePathWithinMapping
|
||||
*/
|
||||
private class PathExposingHandlerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final String bestMatchingPattern;
|
||||
|
||||
private final @Nullable PathPattern bestMatchingPathPattern;
|
||||
|
||||
private final String pathWithinMapping;
|
||||
|
||||
public PathExposingHandlerInterceptor(String bestMatchingPattern, String pathWithinMapping) {
|
||||
this.bestMatchingPattern = bestMatchingPattern;
|
||||
this.bestMatchingPathPattern = null;
|
||||
this.pathWithinMapping = pathWithinMapping;
|
||||
}
|
||||
|
||||
public PathExposingHandlerInterceptor(PathPattern bestMatchingPattern, String pathWithinMapping) {
|
||||
this.bestMatchingPattern = bestMatchingPattern.getPatternString();
|
||||
this.bestMatchingPathPattern = bestMatchingPattern;
|
||||
this.pathWithinMapping = pathWithinMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);
|
||||
if (this.bestMatchingPathPattern != null) {
|
||||
exposePathWithinMapping(this.bestMatchingPathPattern, this.pathWithinMapping, request);
|
||||
}
|
||||
else {
|
||||
exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);
|
||||
}
|
||||
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
|
||||
request.setAttribute(INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings());
|
||||
return true;
|
||||
|
||||
+4
@@ -37,6 +37,7 @@ import org.springframework.web.servlet.function.ServerResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -174,6 +175,9 @@ class RouterFunctionMappingTests {
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo("/match");
|
||||
assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_PATH_PATTERN_ATTRIBUTE))
|
||||
.isInstanceOfSatisfying(PathPattern.class,
|
||||
pattern -> assertThat(pattern.getPatternString()).isEqualTo("/match"));
|
||||
assertThat(ServerHttpObservationFilter.findObservationContext(request))
|
||||
.hasValueSatisfying(context -> assertThat(context.getPathPattern()).isEqualTo("/match"));
|
||||
assertThat(request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(handlerFunction);
|
||||
|
||||
+27
@@ -42,12 +42,15 @@ import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Named.named;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE;
|
||||
import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATH_PATTERN_ATTRIBUTE;
|
||||
import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE;
|
||||
import static org.springframework.web.servlet.HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE;
|
||||
import static org.springframework.web.servlet.HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
|
||||
@@ -99,6 +102,30 @@ class SimpleUrlHandlerMappingTests {
|
||||
assertThat(request.getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE)).isEqualTo(mainController);
|
||||
}
|
||||
|
||||
@HandlerMappingsTest
|
||||
void resolveBestMatchingPathPatternAttribute(SimpleUrlHandlerMapping handlerMapping) throws Exception {
|
||||
StaticApplicationContext applicationContext = new StaticApplicationContext();
|
||||
applicationContext.registerSingleton("mainController", Object.class);
|
||||
Object mainController = applicationContext.getBean("mainController");
|
||||
handlerMapping.setUrlMap(Map.of("/welcome*", "mainController"));
|
||||
handlerMapping.setApplicationContext(applicationContext);
|
||||
|
||||
boolean usePathPatterns = handlerMapping.getPatternParser() != null;
|
||||
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/welcome.x", usePathPatterns);
|
||||
HandlerExecutionChain chain = getHandler(handlerMapping, request);
|
||||
|
||||
assertThat(chain.getHandler()).isSameAs(mainController);
|
||||
assertThat(request.getAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE)).isEqualTo("/welcome*");
|
||||
if (usePathPatterns) {
|
||||
assertThat(request.getAttribute(BEST_MATCHING_PATH_PATTERN_ATTRIBUTE))
|
||||
.isInstanceOfSatisfying(PathPattern.class,
|
||||
pattern -> assertThat(pattern.getPatternString()).isEqualTo("/welcome*"));
|
||||
}
|
||||
else {
|
||||
assertThat(request.getAttribute(BEST_MATCHING_PATH_PATTERN_ATTRIBUTE)).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@HandlerMappingsTest
|
||||
void resolvePatternFromMap(SimpleUrlHandlerMapping handlerMapping) throws Exception {
|
||||
StaticApplicationContext applicationContext = new StaticApplicationContext();
|
||||
|
||||
+1
@@ -316,6 +316,7 @@ class RequestMappingInfoHandlerMappingTests {
|
||||
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)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user