Merge branch '6.2.x'

This commit is contained in:
rstoyanchev
2025-09-25 12:22:29 +01:00
3 changed files with 136 additions and 45 deletions
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -43,8 +44,8 @@ import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
/**
* {@link jakarta.servlet.Filter} that modifies the URL, and then redirects or
* wraps the request to apply the change.
* {@link jakarta.servlet.Filter} that modifies the URL, and then either
* redirects or wraps the request to effect the change.
*
* <p>To create an instance, you can use the following:
*
@@ -55,8 +56,8 @@ import org.springframework.web.util.pattern.PathPatternParser;
* .build();
* </pre>
*
* <p>This {@code Filter} should be ordered after {@link ForwardedHeaderFilter}
* and before any security filters.
* <p>This {@code Filter} should be ordered after {@link ForwardedHeaderFilter},
* before {@link ServletRequestPathFilter}, and before security filters.
*
* @author Rossen Stoyanchev
* @since 6.2
@@ -74,41 +75,23 @@ public final class UrlHandlerFilter extends OncePerRequestFilter {
}
@Override
protected boolean shouldNotFilterAsyncDispatch() {
return false;
}
@Override
protected boolean shouldNotFilterErrorDispatch() {
return false;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
RequestPath previousPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
RequestPath path = previousPath;
try {
if (path == null) {
path = ServletRequestPathUtils.parseAndCache(request);
RequestPath path = (ServletRequestPathUtils.hasParsedRequestPath(request) ?
ServletRequestPathUtils.getParsedRequestPath(request) :
ServletRequestPathUtils.parse(request));
for (Map.Entry<Handler, List<PathPattern>> entry : this.handlers.entrySet()) {
if (!entry.getKey().supports(request, path)) {
continue;
}
for (Map.Entry<Handler, List<PathPattern>> entry : this.handlers.entrySet()) {
if (!entry.getKey().supports(request, path)) {
continue;
for (PathPattern pattern : entry.getValue()) {
if (pattern.matches(path)) {
entry.getKey().handle(request, response, chain);
return;
}
for (PathPattern pattern : entry.getValue()) {
if (pattern.matches(path)) {
entry.getKey().handle(request, response, chain);
return;
}
}
}
}
finally {
if (previousPath != null) {
ServletRequestPathUtils.setParsedRequestPath(previousPath, request);
}
}
@@ -348,7 +331,16 @@ public final class UrlHandlerFilter extends OncePerRequestFilter {
hasPathInfo ? servletPath : trimTrailingSlash(servletPath),
hasPathInfo ? trimTrailingSlash(pathInfo) : pathInfo);
chain.doFilter(request, response);
RequestPath previousPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.clearParsedRequestPath(request);
try {
chain.doFilter(request, response);
}
finally {
if (previousPath != null) {
ServletRequestPathUtils.setParsedRequestPath(previousPath, request);
}
}
}
}
@@ -378,22 +370,30 @@ public final class UrlHandlerFilter extends OncePerRequestFilter {
@Override
public String getRequestURI() {
return this.requestURI;
return (isForward() ? getDelegate().getRequestURI() : this.requestURI);
}
@Override
public StringBuffer getRequestURL() {
return this.requestURL;
return (isForward() ? getDelegate().getRequestURL() : this.requestURL);
}
@Override
public String getServletPath() {
return this.servletPath;
return (isForward() ? getDelegate().getServletPath() : this.servletPath);
}
@Override
public String getPathInfo() {
return this.pathInfo;
return (isForward() ? getDelegate().getPathInfo() : this.pathInfo);
}
private boolean isForward() {
return (getDispatcherType() == DispatcherType.FORWARD);
}
private HttpServletRequest getDelegate() {
return (HttpServletRequest) getRequest();
}
}
@@ -52,16 +52,19 @@ public abstract class ServletRequestPathUtils {
/**
* Parse the {@link HttpServletRequest#getRequestURI() requestURI} to a
* {@link RequestPath} and save it in the request attribute
* {@link #PATH_ATTRIBUTE} for subsequent use with
* {@link org.springframework.web.util.pattern.PathPattern parsed patterns}.
* {@link RequestPath}.
* <p>The returned {@code RequestPath} will have both the contextPath and any
* servletPath prefix omitted from the {@link RequestPath#pathWithinApplication()
* pathWithinApplication} it exposes.
* <p>This method is typically called by the {@code DispatcherServlet} to determine
* if any {@code HandlerMapping} indicates that it uses parsed patterns.
* After that the pre-parsed and cached {@code RequestPath} can be accessed
* through {@link #getParsedRequestPath(ServletRequest)}.
* @since 6.2.12
*/
public static RequestPath parse(HttpServletRequest request) {
return ServletRequestPath.parse(request);
}
/**
* Variant of {@link #parse(HttpServletRequest)} that also saves the parsed
* path in the request attribute {@link #PATH_ATTRIBUTE}.
*/
public static RequestPath parseAndCache(HttpServletRequest request) {
RequestPath requestPath = ServletRequestPath.parse(request);