Request attribute cache for resolved lookupPath
See gh-22644
This commit is contained in:
		
							parent
							
								
									bb9fcad58a
								
							
						
					
					
						commit
						254f06e1a1
					
				|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -91,6 +91,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont | |||
| 		if (request == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		// Ignore LOOKUP_PATH attribute, use our own "fixed" UrlPathHelper with decoding off | ||||
| 		String path = this.urlPathHelper.getLookupPathForRequest(request); | ||||
| 		String extension = UriUtils.extractFileExtension(path); | ||||
| 		return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2017 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -45,6 +45,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource | |||
| 
 | ||||
| 	private UrlPathHelper urlPathHelper = new UrlPathHelper(); | ||||
| 
 | ||||
| 	@Nullable | ||||
| 	private String lookupPathAttributeName; | ||||
| 
 | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Set the PathMatcher implementation to use for matching URL paths | ||||
|  | @ -72,6 +75,17 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource | |||
| 		this.urlPathHelper.setUrlDecode(urlDecode); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Optionally configure the name of the attribute that caches the lookupPath. | ||||
| 	 * This is used to make the call to | ||||
| 	 * {@link UrlPathHelper#getLookupPathForRequest(HttpServletRequest, String)} | ||||
| 	 * @param lookupPathAttributeName the request attribute to check | ||||
| 	 * @since 5.2 | ||||
| 	 */ | ||||
| 	public void setLookupPathAttributeName(@Nullable String lookupPathAttributeName) { | ||||
| 		this.lookupPathAttributeName = lookupPathAttributeName; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Shortcut to same property on underlying {@link #setUrlPathHelper UrlPathHelper}. | ||||
| 	 * @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean) | ||||
|  | @ -117,7 +131,7 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource | |||
| 	@Override | ||||
| 	@Nullable | ||||
| 	public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, this.lookupPathAttributeName); | ||||
| 		for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) { | ||||
| 			if (this.pathMatcher.match(entry.getKey(), lookupPath)) { | ||||
| 				return entry.getValue(); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -175,6 +175,26 @@ public class UrlPathHelper { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Variant of {@link #getLookupPathForRequest(HttpServletRequest)} that | ||||
| 	 * automates checking for a previously computed lookupPath saved as a | ||||
| 	 * request attribute. The attribute is only used for lookup purposes. | ||||
| 	 * @param request current HTTP request | ||||
| 	 * @param lookupPathAttributeName the request attribute to check | ||||
| 	 * @return the lookup path | ||||
| 	 * @since 5.2 | ||||
| 	 * @see org.springframework.web.servlet.HandlerMapping#LOOKUP_PATH | ||||
| 	 */ | ||||
| 	public String getLookupPathForRequest(HttpServletRequest request, @Nullable String lookupPathAttributeName) { | ||||
| 		if (lookupPathAttributeName != null) { | ||||
| 			String result = (String) request.getAttribute(lookupPathAttributeName); | ||||
| 			if (result != null) { | ||||
| 				return result; | ||||
| 			} | ||||
| 		} | ||||
| 		return getLookupPathForRequest(request); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Return the path within the servlet mapping for the given request, | ||||
| 	 * i.e. the part of the request's URL beyond the part that called the servlet, | ||||
|  |  | |||
|  | @ -62,6 +62,15 @@ public interface HandlerMapping { | |||
| 	 */ | ||||
| 	String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler"; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Name of the {@link HttpServletRequest} attribute that contains the path | ||||
| 	 * used to look up the matching handler, which depending on the configured | ||||
| 	 * {@link org.springframework.web.util.UrlPathHelper} could be the full path | ||||
| 	 * or without the context path, decoded or not, etc. | ||||
| 	 * @since 5.2 | ||||
| 	 */ | ||||
| 	String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath"; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Name of the {@link HttpServletRequest} attribute that contains the path | ||||
| 	 * within the handler mapping, in case of a pattern match, or the full | ||||
|  |  | |||
|  | @ -212,6 +212,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport | |||
| 			source.setCorsConfigurations(corsConfigurations); | ||||
| 			source.setPathMatcher(this.pathMatcher); | ||||
| 			source.setUrlPathHelper(this.urlPathHelper); | ||||
| 			source.setLookupPathAttributeName(LOOKUP_PATH); | ||||
| 			this.corsConfigurationSource = source; | ||||
| 		} | ||||
| 		else { | ||||
|  | @ -463,7 +464,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport | |||
| 		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? | ||||
| 				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); | ||||
| 
 | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH); | ||||
| 		for (HandlerInterceptor interceptor : this.adaptedInterceptors) { | ||||
| 			if (interceptor instanceof MappedInterceptor) { | ||||
| 				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; | ||||
|  |  | |||
|  | @ -355,6 +355,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap | |||
| 	@Override | ||||
| 	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); | ||||
| 		request.setAttribute(LOOKUP_PATH, lookupPath); | ||||
| 		this.mappingRegistry.acquireReadLock(); | ||||
| 		try { | ||||
| 			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); | ||||
|  |  | |||
|  | @ -120,6 +120,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i | |||
| 	@Nullable | ||||
| 	protected Object getHandlerInternal(HttpServletRequest request) throws Exception { | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); | ||||
| 		request.setAttribute(LOOKUP_PATH, lookupPath); | ||||
| 		Object handler = lookupHandler(lookupPath, request); | ||||
| 		if (handler == null) { | ||||
| 			// We need to care for the default handler directly, since we need to | ||||
|  | @ -291,7 +292,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i | |||
| 	@Override | ||||
| 	@Nullable | ||||
| 	public RequestMatchResult match(HttpServletRequest request, String pattern) { | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH); | ||||
| 		if (getPathMatcher().match(pattern, lookupPath)) { | ||||
| 			return new RequestMatchResult(pattern, lookupPath, getPathMatcher()); | ||||
| 		} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -110,7 +110,7 @@ public class UrlFilenameViewController extends AbstractUrlViewController { | |||
| 	protected String extractOperableUrl(HttpServletRequest request) { | ||||
| 		String urlPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); | ||||
| 		if (!StringUtils.hasText(urlPath)) { | ||||
| 			urlPath = getUrlPathHelper().getLookupPathForRequest(request); | ||||
| 			urlPath = getUrlPathHelper().getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 		} | ||||
| 		return urlPath; | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -30,6 +30,7 @@ import org.springframework.util.AntPathMatcher; | |||
| import org.springframework.util.Assert; | ||||
| import org.springframework.util.PathMatcher; | ||||
| import org.springframework.web.servlet.HandlerInterceptor; | ||||
| import org.springframework.web.servlet.HandlerMapping; | ||||
| import org.springframework.web.servlet.ModelAndView; | ||||
| import org.springframework.web.servlet.support.WebContentGenerator; | ||||
| import org.springframework.web.util.UrlPathHelper; | ||||
|  | @ -169,7 +170,7 @@ public class WebContentInterceptor extends WebContentGenerator implements Handle | |||
| 
 | ||||
| 		checkRequest(request); | ||||
| 
 | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 
 | ||||
| 		CacheControl cacheControl = lookupCacheControl(lookupPath); | ||||
| 		Integer cacheSeconds = lookupCacheSeconds(lookupPath); | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ import org.springframework.lang.Nullable; | |||
| import org.springframework.util.AntPathMatcher; | ||||
| import org.springframework.util.PathMatcher; | ||||
| import org.springframework.util.StringUtils; | ||||
| import org.springframework.web.servlet.HandlerMapping; | ||||
| import org.springframework.web.util.UrlPathHelper; | ||||
| 
 | ||||
| /** | ||||
|  | @ -212,7 +213,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat | |||
| 		if (this.patterns.isEmpty()) { | ||||
| 			return this; | ||||
| 		} | ||||
| 		String lookupPath = this.pathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 		List<String> matches = getMatchingPatterns(lookupPath); | ||||
| 		return !matches.isEmpty() ? new PatternsRequestCondition(new LinkedHashSet<>(matches), this) : null; | ||||
| 	} | ||||
|  | @ -287,7 +288,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat | |||
| 	 */ | ||||
| 	@Override | ||||
| 	public int compareTo(PatternsRequestCondition other, HttpServletRequest request) { | ||||
| 		String lookupPath = this.pathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 		Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath); | ||||
| 		Iterator<String> iterator = this.patterns.iterator(); | ||||
| 		Iterator<String> iteratorOther = other.patterns.iterator(); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -340,7 +340,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi | |||
| 			return null; | ||||
| 		} | ||||
| 		Set<String> patterns = matchingInfo.getPatternsCondition().getPatterns(); | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); | ||||
| 		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH); | ||||
| 		return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher()); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2018 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -34,6 +34,7 @@ import org.springframework.lang.Nullable; | |||
| import org.springframework.util.AntPathMatcher; | ||||
| import org.springframework.util.PathMatcher; | ||||
| import org.springframework.util.StringUtils; | ||||
| import org.springframework.web.servlet.HandlerMapping; | ||||
| import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; | ||||
| import org.springframework.web.util.UrlPathHelper; | ||||
| 
 | ||||
|  | @ -180,7 +181,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed | |||
| 	private int getLookupPathIndex(HttpServletRequest request) { | ||||
| 		UrlPathHelper pathHelper = getUrlPathHelper(); | ||||
| 		String requestUri = pathHelper.getRequestUri(request); | ||||
| 		String lookupPath = pathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 		return requestUri.indexOf(lookupPath); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| /* | ||||
|  * Copyright 2002-2017 the original author or authors. | ||||
|  * Copyright 2002-2019 the original author or authors. | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  | @ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest; | |||
| import org.springframework.lang.Nullable; | ||||
| import org.springframework.util.Assert; | ||||
| import org.springframework.util.StringUtils; | ||||
| import org.springframework.web.servlet.HandlerMapping; | ||||
| import org.springframework.web.servlet.RequestToViewNameTranslator; | ||||
| import org.springframework.web.util.UrlPathHelper; | ||||
| 
 | ||||
|  | @ -167,7 +168,7 @@ public class DefaultRequestToViewNameTranslator implements RequestToViewNameTran | |||
| 	 */ | ||||
| 	@Override | ||||
| 	public String getViewName(HttpServletRequest request) { | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); | ||||
| 		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH); | ||||
| 		return (this.prefix + transformPath(lookupPath) + this.suffix); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue