Description
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.