Skip to content

Commit 254f06e

Browse files
committed
Request attribute cache for resolved lookupPath
See gh-22644
1 parent bb9fcad commit 254f06e

13 files changed

+69
-18
lines changed

spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -91,6 +91,7 @@ protected String getMediaTypeKey(NativeWebRequest webRequest) {
9191
if (request == null) {
9292
return null;
9393
}
94+
// Ignore LOOKUP_PATH attribute, use our own "fixed" UrlPathHelper with decoding off
9495
String path = this.urlPathHelper.getLookupPathForRequest(request);
9596
String extension = UriUtils.extractFileExtension(path);
9697
return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null);

spring-web/src/main/java/org/springframework/web/cors/UrlBasedCorsConfigurationSource.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,6 +45,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
4545

4646
private UrlPathHelper urlPathHelper = new UrlPathHelper();
4747

48+
@Nullable
49+
private String lookupPathAttributeName;
50+
4851

4952
/**
5053
* Set the PathMatcher implementation to use for matching URL paths
@@ -72,6 +75,17 @@ public void setUrlDecode(boolean urlDecode) {
7275
this.urlPathHelper.setUrlDecode(urlDecode);
7376
}
7477

78+
/**
79+
* Optionally configure the name of the attribute that caches the lookupPath.
80+
* This is used to make the call to
81+
* {@link UrlPathHelper#getLookupPathForRequest(HttpServletRequest, String)}
82+
* @param lookupPathAttributeName the request attribute to check
83+
* @since 5.2
84+
*/
85+
public void setLookupPathAttributeName(@Nullable String lookupPathAttributeName) {
86+
this.lookupPathAttributeName = lookupPathAttributeName;
87+
}
88+
7589
/**
7690
* Shortcut to same property on underlying {@link #setUrlPathHelper UrlPathHelper}.
7791
* @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
@@ -117,7 +131,7 @@ public void registerCorsConfiguration(String path, CorsConfiguration config) {
117131
@Override
118132
@Nullable
119133
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
120-
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
134+
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, this.lookupPathAttributeName);
121135
for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
122136
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
123137
return entry.getValue();

spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -175,6 +175,26 @@ public String getLookupPathForRequest(HttpServletRequest request) {
175175
}
176176
}
177177

178+
/**
179+
* Variant of {@link #getLookupPathForRequest(HttpServletRequest)} that
180+
* automates checking for a previously computed lookupPath saved as a
181+
* request attribute. The attribute is only used for lookup purposes.
182+
* @param request current HTTP request
183+
* @param lookupPathAttributeName the request attribute to check
184+
* @return the lookup path
185+
* @since 5.2
186+
* @see org.springframework.web.servlet.HandlerMapping#LOOKUP_PATH
187+
*/
188+
public String getLookupPathForRequest(HttpServletRequest request, @Nullable String lookupPathAttributeName) {
189+
if (lookupPathAttributeName != null) {
190+
String result = (String) request.getAttribute(lookupPathAttributeName);
191+
if (result != null) {
192+
return result;
193+
}
194+
}
195+
return getLookupPathForRequest(request);
196+
}
197+
178198
/**
179199
* Return the path within the servlet mapping for the given request,
180200
* i.e. the part of the request's URL beyond the part that called the servlet,

spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java

+9
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ public interface HandlerMapping {
6262
*/
6363
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
6464

65+
/**
66+
* Name of the {@link HttpServletRequest} attribute that contains the path
67+
* used to look up the matching handler, which depending on the configured
68+
* {@link org.springframework.web.util.UrlPathHelper} could be the full path
69+
* or without the context path, decoded or not, etc.
70+
* @since 5.2
71+
*/
72+
String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";
73+
6574
/**
6675
* Name of the {@link HttpServletRequest} attribute that contains the path
6776
* within the handler mapping, in case of a pattern match, or the full

spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ public void setCorsConfigurations(Map<String, CorsConfiguration> corsConfigurati
212212
source.setCorsConfigurations(corsConfigurations);
213213
source.setPathMatcher(this.pathMatcher);
214214
source.setUrlPathHelper(this.urlPathHelper);
215+
source.setLookupPathAttributeName(LOOKUP_PATH);
215216
this.corsConfigurationSource = source;
216217
}
217218
else {
@@ -463,7 +464,7 @@ protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpSer
463464
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
464465
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
465466

466-
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
467+
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
467468
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
468469
if (interceptor instanceof MappedInterceptor) {
469470
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;

spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ protected void handlerMethodsInitialized(Map<T, HandlerMethod> handlerMethods) {
355355
@Override
356356
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
357357
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
358+
request.setAttribute(LOOKUP_PATH, lookupPath);
358359
this.mappingRegistry.acquireReadLock();
359360
try {
360361
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);

spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public void setLazyInitHandlers(boolean lazyInitHandlers) {
120120
@Nullable
121121
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
122122
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
123+
request.setAttribute(LOOKUP_PATH, lookupPath);
123124
Object handler = lookupHandler(lookupPath, request);
124125
if (handler == null) {
125126
// We need to care for the default handler directly, since we need to
@@ -291,7 +292,7 @@ protected void exposeUriTemplateVariables(Map<String, String> uriTemplateVariabl
291292
@Override
292293
@Nullable
293294
public RequestMatchResult match(HttpServletRequest request, String pattern) {
294-
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
295+
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH);
295296
if (getPathMatcher().match(pattern, lookupPath)) {
296297
return new RequestMatchResult(pattern, lookupPath, getPathMatcher());
297298
}

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/UrlFilenameViewController.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -110,7 +110,7 @@ protected String getViewNameForRequest(HttpServletRequest request) {
110110
protected String extractOperableUrl(HttpServletRequest request) {
111111
String urlPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
112112
if (!StringUtils.hasText(urlPath)) {
113-
urlPath = getUrlPathHelper().getLookupPathForRequest(request);
113+
urlPath = getUrlPathHelper().getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
114114
}
115115
return urlPath;
116116
}

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/WebContentInterceptor.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
3030
import org.springframework.util.Assert;
3131
import org.springframework.util.PathMatcher;
3232
import org.springframework.web.servlet.HandlerInterceptor;
33+
import org.springframework.web.servlet.HandlerMapping;
3334
import org.springframework.web.servlet.ModelAndView;
3435
import org.springframework.web.servlet.support.WebContentGenerator;
3536
import org.springframework.web.util.UrlPathHelper;
@@ -169,7 +170,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
169170

170171
checkRequest(request);
171172

172-
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
173+
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
173174

174175
CacheControl cacheControl = lookupCacheControl(lookupPath);
175176
Integer cacheSeconds = lookupCacheSeconds(lookupPath);

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.util.AntPathMatcher;
3232
import org.springframework.util.PathMatcher;
3333
import org.springframework.util.StringUtils;
34+
import org.springframework.web.servlet.HandlerMapping;
3435
import org.springframework.web.util.UrlPathHelper;
3536

3637
/**
@@ -212,7 +213,7 @@ public PatternsRequestCondition getMatchingCondition(HttpServletRequest request)
212213
if (this.patterns.isEmpty()) {
213214
return this;
214215
}
215-
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
216+
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
216217
List<String> matches = getMatchingPatterns(lookupPath);
217218
return !matches.isEmpty() ? new PatternsRequestCondition(new LinkedHashSet<>(matches), this) : null;
218219
}
@@ -287,7 +288,7 @@ private String getMatchingPattern(String pattern, String lookupPath) {
287288
*/
288289
@Override
289290
public int compareTo(PatternsRequestCondition other, HttpServletRequest request) {
290-
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
291+
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
291292
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath);
292293
Iterator<String> iterator = this.patterns.iterator();
293294
Iterator<String> iteratorOther = other.patterns.iterator();

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -340,7 +340,7 @@ public RequestMatchResult match(HttpServletRequest request, String pattern) {
340340
return null;
341341
}
342342
Set<String> patterns = matchingInfo.getPatternsCondition().getPatterns();
343-
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
343+
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH);
344344
return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher());
345345
}
346346

spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
3434
import org.springframework.util.AntPathMatcher;
3535
import org.springframework.util.PathMatcher;
3636
import org.springframework.util.StringUtils;
37+
import org.springframework.web.servlet.HandlerMapping;
3738
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
3839
import org.springframework.web.util.UrlPathHelper;
3940

@@ -180,7 +181,7 @@ public final String getForRequestUrl(HttpServletRequest request, String requestU
180181
private int getLookupPathIndex(HttpServletRequest request) {
181182
UrlPathHelper pathHelper = getUrlPathHelper();
182183
String requestUri = pathHelper.getRequestUri(request);
183-
String lookupPath = pathHelper.getLookupPathForRequest(request);
184+
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
184185
return requestUri.indexOf(lookupPath);
185186
}
186187

spring-webmvc/src/main/java/org/springframework/web/servlet/view/DefaultRequestToViewNameTranslator.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import org.springframework.lang.Nullable;
2222
import org.springframework.util.Assert;
2323
import org.springframework.util.StringUtils;
24+
import org.springframework.web.servlet.HandlerMapping;
2425
import org.springframework.web.servlet.RequestToViewNameTranslator;
2526
import org.springframework.web.util.UrlPathHelper;
2627

@@ -167,7 +168,7 @@ public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
167168
*/
168169
@Override
169170
public String getViewName(HttpServletRequest request) {
170-
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
171+
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
171172
return (this.prefix + transformPath(lookupPath) + this.suffix);
172173
}
173174

0 commit comments

Comments
 (0)