|
|
|
|
@ -19,6 +19,8 @@ package org.springframework.web.servlet.handler;
@@ -19,6 +19,8 @@ package org.springframework.web.servlet.handler;
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.Enumeration; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Properties; |
|
|
|
|
@ -138,16 +140,17 @@ public class HandlerMappingIntrospector
@@ -138,16 +140,17 @@ public class HandlerMappingIntrospector
|
|
|
|
|
*/ |
|
|
|
|
@Nullable |
|
|
|
|
public MatchableHandlerMapping getMatchableHandlerMapping(HttpServletRequest request) throws Exception { |
|
|
|
|
HttpServletRequest wrappedRequest = new RequestAttributeChangeIgnoringWrapper(request); |
|
|
|
|
HttpServletRequest wrappedRequest = new AttributesPreservingRequest(request); |
|
|
|
|
return doWithMatchingMapping(wrappedRequest, false, (matchedMapping, executionChain) -> { |
|
|
|
|
if (matchedMapping instanceof MatchableHandlerMapping) { |
|
|
|
|
PathPatternMatchableHandlerMapping mapping = this.pathPatternHandlerMappings.get(matchedMapping); |
|
|
|
|
if (mapping != null) { |
|
|
|
|
RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request); |
|
|
|
|
return mapping.decorate(requestPath); |
|
|
|
|
RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(wrappedRequest); |
|
|
|
|
return new PathSettingHandlerMapping(mapping, requestPath); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
return (MatchableHandlerMapping) matchedMapping; |
|
|
|
|
String lookupPath = (String) wrappedRequest.getAttribute(UrlPathHelper.PATH_ATTRIBUTE); |
|
|
|
|
return new PathSettingHandlerMapping((MatchableHandlerMapping) matchedMapping, lookupPath); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
throw new IllegalStateException("HandlerMapping is not a MatchableHandlerMapping"); |
|
|
|
|
@ -157,7 +160,7 @@ public class HandlerMappingIntrospector
@@ -157,7 +160,7 @@ public class HandlerMappingIntrospector
|
|
|
|
|
@Override |
|
|
|
|
@Nullable |
|
|
|
|
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { |
|
|
|
|
RequestAttributeChangeIgnoringWrapper wrappedRequest = new RequestAttributeChangeIgnoringWrapper(request); |
|
|
|
|
AttributesPreservingRequest wrappedRequest = new AttributesPreservingRequest(request); |
|
|
|
|
return doWithMatchingMappingIgnoringException(wrappedRequest, (handlerMapping, executionChain) -> { |
|
|
|
|
for (HandlerInterceptor interceptor : executionChain.getInterceptorList()) { |
|
|
|
|
if (interceptor instanceof CorsConfigurationSource) { |
|
|
|
|
@ -272,19 +275,83 @@ public class HandlerMappingIntrospector
@@ -272,19 +275,83 @@ public class HandlerMappingIntrospector
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Request wrapper that ignores request attribute changes. |
|
|
|
|
* Request wrapper that buffers request attributes in order protect the |
|
|
|
|
* underlying request from attribute changes. |
|
|
|
|
*/ |
|
|
|
|
private static class RequestAttributeChangeIgnoringWrapper extends HttpServletRequestWrapper { |
|
|
|
|
private static class AttributesPreservingRequest extends HttpServletRequestWrapper { |
|
|
|
|
|
|
|
|
|
RequestAttributeChangeIgnoringWrapper(HttpServletRequest request) { |
|
|
|
|
private final Map<String, Object> attributes; |
|
|
|
|
|
|
|
|
|
AttributesPreservingRequest(HttpServletRequest request) { |
|
|
|
|
super(request); |
|
|
|
|
this.attributes = initAttributes(request); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Map<String, Object> initAttributes(HttpServletRequest request) { |
|
|
|
|
Map<String, Object> map = new HashMap<>(); |
|
|
|
|
Enumeration<String> names = request.getAttributeNames(); |
|
|
|
|
while (names.hasMoreElements()) { |
|
|
|
|
String name = names.nextElement(); |
|
|
|
|
map.put(name, request.getAttribute(name)); |
|
|
|
|
} |
|
|
|
|
return map; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void setAttribute(String name, Object value) { |
|
|
|
|
if (name.equals(ServletRequestPathUtils.PATH_ATTRIBUTE) || name.equals(UrlPathHelper.PATH_ATTRIBUTE)) { |
|
|
|
|
super.setAttribute(name, value); |
|
|
|
|
this.attributes.put(name, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Object getAttribute(String name) { |
|
|
|
|
return this.attributes.get(name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Enumeration<String> getAttributeNames() { |
|
|
|
|
return Collections.enumeration(this.attributes.keySet()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void removeAttribute(String name) { |
|
|
|
|
this.attributes.remove(name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class PathSettingHandlerMapping implements MatchableHandlerMapping { |
|
|
|
|
|
|
|
|
|
private final MatchableHandlerMapping delegate; |
|
|
|
|
|
|
|
|
|
private final Object path; |
|
|
|
|
|
|
|
|
|
private final String pathAttributeName; |
|
|
|
|
|
|
|
|
|
PathSettingHandlerMapping(MatchableHandlerMapping delegate, Object path) { |
|
|
|
|
this.delegate = delegate; |
|
|
|
|
this.path = path; |
|
|
|
|
this.pathAttributeName = (path instanceof RequestPath ? |
|
|
|
|
ServletRequestPathUtils.PATH_ATTRIBUTE : UrlPathHelper.PATH_ATTRIBUTE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
@Override |
|
|
|
|
public RequestMatchResult match(HttpServletRequest request, String pattern) { |
|
|
|
|
Object previousPath = request.getAttribute(this.pathAttributeName); |
|
|
|
|
request.setAttribute(this.pathAttributeName, this.path); |
|
|
|
|
try { |
|
|
|
|
return this.delegate.match(request, pattern); |
|
|
|
|
} |
|
|
|
|
finally { |
|
|
|
|
request.setAttribute(this.pathAttributeName, previousPath); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
@Override |
|
|
|
|
public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { |
|
|
|
|
return this.delegate.getHandler(request); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|