Discovered whilst working on spring-projects/spring-boot#24645. Running CorsSampleActuatorApplicationTests.preflightRequestToEndpointShouldReturnOk from this branch should replicate the problem.
This issue is a quite subtle and hard to replicate. I've found it to cause problems for CorsFilter as well as MvcRequestMatcher in Spring Security. It appears that HandlerMappingIntrospector can fail to find mappings if they are configured with a PathPattern.
In AbstractHandlerMapping.initLookupPath there's the following branch:
if (usesPathPatterns()) {
request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
String lookupPath = requestPath.pathWithinApplication().value();
return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
}
else {
return getUrlPathHelper().resolveAndCacheLookupPath(request);
}
This means that ServletRequestPathUtils.getParsedRequestPath(request) is called when a PathPattern is set. That code will fail if request.getAttribute(PATH_ATTRIBUTE) is null.
Usually HandlerMappers are only called from the DispatcherServlet which has the following logic:
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.parseAndCache(request);
}
The problem is that HandlerMappingIntrospector is designed to be called from a Filter which means that it can be executed before the DisatcherServlet runs.
Discovered whilst working on spring-projects/spring-boot#24645. Running
CorsSampleActuatorApplicationTests.preflightRequestToEndpointShouldReturnOkfrom this branch should replicate the problem.This issue is a quite subtle and hard to replicate. I've found it to cause problems for
CorsFilteras well asMvcRequestMatcherin Spring Security. It appears thatHandlerMappingIntrospectorcan fail to find mappings if they are configured with aPathPattern.In
AbstractHandlerMapping.initLookupPaththere's the following branch:This means that
ServletRequestPathUtils.getParsedRequestPath(request)is called when aPathPatternis set. That code will fail ifrequest.getAttribute(PATH_ATTRIBUTE)isnull.Usually
HandlerMappersare only called from theDispatcherServletwhich has the following logic:The problem is that
HandlerMappingIntrospectoris designed to be called from aFilterwhich means that it can be executed before theDisatcherServletruns.