From ae7cff35dcdc85cef1662ef7698dd988d35bc9e6 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 20 Dec 2022 09:39:15 +0000 Subject: [PATCH] Polishing --- .../web/util/ServletRequestPathUtils.java | 59 +++++++------------ .../web/util/UrlPathHelper.java | 15 ++--- 2 files changed, 27 insertions(+), 47 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/ServletRequestPathUtils.java b/spring-web/src/main/java/org/springframework/web/util/ServletRequestPathUtils.java index 3cf02804ea..675495ede2 100644 --- a/spring-web/src/main/java/org/springframework/web/util/ServletRequestPathUtils.java +++ b/spring-web/src/main/java/org/springframework/web/util/ServletRequestPathUtils.java @@ -113,25 +113,25 @@ public abstract class ServletRequestPathUtils { // Methods to select either parsed RequestPath or resolved String lookupPath /** - * Return the {@link UrlPathHelper#resolveAndCacheLookupPath pre-resolved} - * String lookupPath or the {@link #parseAndCache(HttpServletRequest) + * Return either a {@link UrlPathHelper#resolveAndCacheLookupPath pre-resolved} + * String lookupPath or a {@link #parseAndCache(HttpServletRequest) * pre-parsed} {@code RequestPath}. *

In Spring MVC, when at least one {@code HandlerMapping} has parsed - * {@code PathPatterns} enabled, the {@code DispatcherServlet} eagerly parses - * and caches the {@code RequestPath} and the same can be also done earlier with + * {@code PathPatterns} enabled, the {@code DispatcherServlet} parses and + * caches the {@code RequestPath} which can be also done even earlier with * {@link org.springframework.web.filter.ServletRequestPathFilter * ServletRequestPathFilter}. In other cases where {@code HandlerMapping}s * use String pattern matching with {@code PathMatcher}, the String - * lookupPath is resolved separately by each {@code HandlerMapping}. + * lookupPath is resolved separately in each {@code HandlerMapping}. * @param request the current request * @return a String lookupPath or a {@code RequestPath} * @throws IllegalArgumentException if neither is available */ public static Object getCachedPath(ServletRequest request) { - // The RequestPath is pre-parsed if any HandlerMapping uses PathPatterns. - // The lookupPath is re-resolved or cleared per HandlerMapping. - // So check for lookupPath first. + // RequestPath is parsed once and cached in the DispatcherServlet if any HandlerMapping uses PathPatterns. + // A String lookupPath is resolved and cached in each HandlerMapping that uses String matching. + // So we try lookupPath first, then RequestPath second String lookupPath = (String) request.getAttribute(UrlPathHelper.PATH_ATTRIBUTE); if (lookupPath != null) { @@ -246,41 +246,24 @@ public abstract class ServletRequestPathUtils { public static RequestPath parse(HttpServletRequest request) { String requestUri = (String) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE); - if (requestUri == null) { - requestUri = request.getRequestURI(); - } - - String servletPathPrefix = Servlet4Delegate.getServletPathPrefix(request); - if (StringUtils.hasText(servletPathPrefix)) { - if (servletPathPrefix.endsWith("/")) { - servletPathPrefix = servletPathPrefix.substring(0, servletPathPrefix.length() - 1); - } - return new ServletRequestPath(requestUri, request.getContextPath(), servletPathPrefix); - } - - return RequestPath.parse(requestUri, request.getContextPath()); + requestUri = (requestUri != null ? requestUri : request.getRequestURI()); + String servletPathPrefix = getServletPathPrefix(request); + return (StringUtils.hasText(servletPathPrefix) ? + new ServletRequestPath(requestUri, request.getContextPath(), servletPathPrefix) : + RequestPath.parse(requestUri, request.getContextPath())); } - } - - - /** - * Inner class to avoid a hard dependency on Servlet 4 {@link HttpServletMapping} - * and {@link MappingMatch} at runtime. - */ - private static class Servlet4Delegate { @Nullable - public static String getServletPathPrefix(HttpServletRequest request) { + private static String getServletPathPrefix(HttpServletRequest request) { HttpServletMapping mapping = (HttpServletMapping) request.getAttribute(RequestDispatcher.INCLUDE_MAPPING); - if (mapping == null) { - mapping = request.getHttpServletMapping(); + mapping = (mapping != null ? mapping : request.getHttpServletMapping()); + if (ObjectUtils.nullSafeEquals(mapping.getMappingMatch(), MappingMatch.PATH)) { + String servletPath = (String) request.getAttribute(WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE); + servletPath = (servletPath != null ? servletPath : request.getServletPath()); + servletPath = (servletPath.endsWith("/") ? servletPath.substring(0, servletPath.length() - 1) : servletPath); + return UriUtils.encodePath(servletPath, StandardCharsets.UTF_8); } - if (!ObjectUtils.nullSafeEquals(mapping.getMappingMatch(), MappingMatch.PATH)) { - return null; - } - String servletPath = (String) request.getAttribute(WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE); - servletPath = (servletPath != null ? servletPath : request.getServletPath()); - return UriUtils.encodePath(servletPath, StandardCharsets.UTF_8); + return null; } } diff --git a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java index 4a7a3b7012..58129e58d2 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java +++ b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java @@ -242,7 +242,7 @@ public class UrlPathHelper { public String getLookupPathForRequest(HttpServletRequest request) { String pathWithinApp = getPathWithinApplication(request); // Always use full path within current servlet context? - if (this.alwaysUseFullPath || skipServletPathDetermination(request)) { + if (this.alwaysUseFullPath || ignoreServletPath(request)) { return pathWithinApp; } // Else, use path within current servlet mapping if applicable @@ -256,16 +256,13 @@ public class UrlPathHelper { } /** - * Check whether servlet path determination can be skipped for the given request. - * @param request current HTTP request - * @return {@code true} if the request mapping has not been achieved using a path - * or if the servlet has been mapped to root; {@code false} otherwise + * Whether we can ignore the servletPath and pathInfo for mapping purposes, + * which is the case when we can establish that the Servlet is not mapped + * by servletPath prefix. */ - private boolean skipServletPathDetermination(HttpServletRequest request) { + private boolean ignoreServletPath(HttpServletRequest request) { HttpServletMapping mapping = (HttpServletMapping) request.getAttribute(RequestDispatcher.INCLUDE_MAPPING); - if (mapping == null) { - mapping = request.getHttpServletMapping(); - } + mapping = (mapping == null ? request.getHttpServletMapping() : mapping); MappingMatch match = mapping.getMappingMatch(); return (match != null && (!match.equals(MappingMatch.PATH) || mapping.getPattern().equals("/*"))); }