diff options
Diffstat (limited to 'spring-webmvc')
13 files changed, 173 insertions, 76 deletions
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java index 117bff35..da03f81f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2018 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. @@ -54,6 +54,13 @@ import javax.servlet.http.HttpServletRequest; public interface HandlerMapping { /** + * Name of the {@link HttpServletRequest} attribute that contains the mapped + * handler for the best matching pattern. + * @since 4.3.21 + */ + String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler"; + + /** * Name of the {@link HttpServletRequest} attribute that contains the path * within the handler mapping, in case of a pattern match, or the full * relevant URI (typically within the DispatcherServlet's mapping) else. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java index b401b525..98c33b9d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java @@ -132,8 +132,8 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti ModelAndView result = doResolveException(request, response, handler, ex); if (result != null) { // Print warn message when warn logger is not enabled... - if (logger.isWarnEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) { - logger.warn("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result)); + if (logger.isDebugEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) { + logger.debug("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result)); } // warnLogger with full stack trace (requires explicit config) logException(ex, request); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index f471b36a..3893b2a0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -367,6 +367,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); } } + request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java index 16a120cb..48571d6b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java @@ -407,6 +407,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request); + request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, handler); request.setAttribute(INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings()); return true; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java index 80ee3852..cca63932 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java @@ -72,8 +72,7 @@ public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionRes } } else if (ex.getCause() instanceof Exception) { - ex = (Exception) ex.getCause(); - return doResolveException(request, response, handler, ex); + return doResolveException(request, response, handler, (Exception) ex.getCause()); } return null; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java index bddd9190..941e47bd 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -41,7 +41,7 @@ import org.springframework.web.multipart.support.RequestPartServletServerHttpReq /** * Resolves the following method arguments: * <ul> - * <li>Annotated with {@code @RequestPart} + * <li>Annotated with @{@link RequestPart} * <li>Of type {@link MultipartFile} in conjunction with Spring's {@link MultipartResolver} abstraction * <li>Of type {@code javax.servlet.http.Part} in conjunction with Servlet 3.0 multipart requests * </ul> @@ -85,11 +85,13 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM /** - * Supports the following: + * Whether the given {@linkplain MethodParameter method parameter} is a multi-part + * supported. Supports the following: * <ul> * <li>annotated with {@code @RequestPart} * <li>of type {@link MultipartFile} unless annotated with {@code @RequestParam} - * <li>of type {@code javax.servlet.http.Part} unless annotated with {@code @RequestParam} + * <li>of type {@code javax.servlet.http.Part} unless annotated with + * {@code @RequestParam} * </ul> */ @Override diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java index a92c33a6..22a14efa 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java @@ -97,6 +97,7 @@ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionRes */ public DefaultHandlerExceptionResolver() { setOrder(Ordered.LOWEST_PRECEDENCE); + setWarnLogCategory(getClass().getName()); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java index 531167c1..d1dee3c9 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java @@ -641,22 +641,25 @@ public class ResourceHttpRequestHandler extends WebContentGenerator */ protected boolean isInvalidPath(String path) { if (path.contains("WEB-INF") || path.contains("META-INF")) { - logger.trace("Path contains \"WEB-INF\" or \"META-INF\"."); + if (logger.isTraceEnabled()) { + logger.trace("Path with \"WEB-INF\" or \"META-INF\": [" + path + "]"); + } return true; } if (path.contains(":/")) { String relativePath = (path.charAt(0) == '/' ? path.substring(1) : path); if (ResourceUtils.isUrl(relativePath) || relativePath.startsWith("url:")) { - logger.trace("Path represents URL or has \"url:\" prefix."); + if (logger.isTraceEnabled()) { + logger.trace("Path represents URL or has \"url:\" prefix: [" + path + "]"); + } return true; } } - if (path.contains("..")) { - path = StringUtils.cleanPath(path); - if (path.contains("../")) { - logger.trace("Path contains \"../\" after call to StringUtils#cleanPath."); - return true; + if (path.contains("..") && StringUtils.cleanPath(path).contains("../")) { + if (logger.isTraceEnabled()) { + logger.trace("Path contains \"../\" after call to StringUtils#cleanPath: [" + path + "]"); } + return true; } return false; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java index d6ca1c33..64dfed2f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 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. @@ -22,6 +22,7 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @@ -34,8 +35,7 @@ import org.springframework.web.util.UrlPathHelper; /** * A filter that wraps the {@link HttpServletResponse} and overrides its * {@link HttpServletResponse#encodeURL(String) encodeURL} method in order to - * translate internal resource request URLs into public URL paths for external - * use. + * translate internal resource request URLs into public URL paths for external use. * * @author Jeremy Grelle * @author Rossen Stoyanchev @@ -50,67 +50,52 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) - throws IOException, ServletException { + throws ServletException, IOException { + if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) { - throw new ServletException("ResourceUrlEncodingFilter just supports HTTP requests"); + throw new ServletException("ResourceUrlEncodingFilter only supports HTTP requests"); } - HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; - filterChain.doFilter(httpRequest, new ResourceUrlEncodingResponseWrapper(httpRequest, httpResponse)); + ResourceUrlEncodingRequestWrapper wrappedRequest = + new ResourceUrlEncodingRequestWrapper((HttpServletRequest) request); + ResourceUrlEncodingResponseWrapper wrappedResponse = + new ResourceUrlEncodingResponseWrapper(wrappedRequest, (HttpServletResponse) response); + filterChain.doFilter(wrappedRequest, wrappedResponse); } - private static class ResourceUrlEncodingResponseWrapper extends HttpServletResponseWrapper { + private static class ResourceUrlEncodingRequestWrapper extends HttpServletRequestWrapper { - private final HttpServletRequest request; + private ResourceUrlProvider resourceUrlProvider; - /* Cache the index and prefix of the path within the DispatcherServlet mapping */ private Integer indexLookupPath; private String prefixLookupPath; - public ResourceUrlEncodingResponseWrapper(HttpServletRequest request, HttpServletResponse wrapped) { - super(wrapped); - this.request = request; + ResourceUrlEncodingRequestWrapper(HttpServletRequest request) { + super(request); } @Override - public String encodeURL(String url) { - ResourceUrlProvider resourceUrlProvider = getResourceUrlProvider(); - if (resourceUrlProvider == null) { - logger.debug("Request attribute exposing ResourceUrlProvider not found"); - return super.encodeURL(url); - } - - initLookupPath(resourceUrlProvider); - if (url.startsWith(this.prefixLookupPath)) { - int suffixIndex = getQueryParamsIndex(url); - String suffix = url.substring(suffixIndex); - String lookupPath = url.substring(this.indexLookupPath, suffixIndex); - lookupPath = resourceUrlProvider.getForLookupPath(lookupPath); - if (lookupPath != null) { - return super.encodeURL(this.prefixLookupPath + lookupPath + suffix); + public void setAttribute(String name, Object value) { + super.setAttribute(name, value); + if (ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR.equals(name)) { + if (value instanceof ResourceUrlProvider) { + initLookupPath((ResourceUrlProvider) value); } } - return super.encodeURL(url); - } - - private ResourceUrlProvider getResourceUrlProvider() { - return (ResourceUrlProvider) this.request.getAttribute( - ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR); } private void initLookupPath(ResourceUrlProvider urlProvider) { + this.resourceUrlProvider = urlProvider; if (this.indexLookupPath == null) { - UrlPathHelper pathHelper = urlProvider.getUrlPathHelper(); - String requestUri = pathHelper.getRequestUri(this.request); - String lookupPath = pathHelper.getLookupPathForRequest(this.request); + UrlPathHelper pathHelper = this.resourceUrlProvider.getUrlPathHelper(); + String requestUri = pathHelper.getRequestUri(this); + String lookupPath = pathHelper.getLookupPathForRequest(this); this.indexLookupPath = requestUri.lastIndexOf(lookupPath); this.prefixLookupPath = requestUri.substring(0, this.indexLookupPath); - if ("/".equals(lookupPath) && !"/".equals(requestUri)) { - String contextPath = pathHelper.getContextPath(this.request); + String contextPath = pathHelper.getContextPath(this); if (requestUri.equals(contextPath)) { this.indexLookupPath = requestUri.length(); this.prefixLookupPath = requestUri; @@ -119,10 +104,48 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean { } } + public String resolveUrlPath(String url) { + if (this.resourceUrlProvider == null) { + logger.trace("ResourceUrlProvider not available via request attribute " + + "ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR"); + return null; + } + if (this.indexLookupPath != null && url.startsWith(this.prefixLookupPath)) { + int suffixIndex = getQueryParamsIndex(url); + String suffix = url.substring(suffixIndex); + String lookupPath = url.substring(this.indexLookupPath, suffixIndex); + lookupPath = this.resourceUrlProvider.getForLookupPath(lookupPath); + if (lookupPath != null) { + return this.prefixLookupPath + lookupPath + suffix; + } + } + return null; + } + private int getQueryParamsIndex(String url) { int index = url.indexOf('?'); return (index > 0 ? index : url.length()); } } + + private static class ResourceUrlEncodingResponseWrapper extends HttpServletResponseWrapper { + + private final ResourceUrlEncodingRequestWrapper request; + + ResourceUrlEncodingResponseWrapper(ResourceUrlEncodingRequestWrapper request, HttpServletResponse wrapped) { + super(wrapped); + this.request = request; + } + + @Override + public String encodeURL(String url) { + String urlPath = this.request.resolveUrlPath(url); + if (urlPath != null) { + return super.encodeURL(urlPath); + } + return super.encodeURL(url); + } + } + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java index 5a181069..6676f2de 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java @@ -38,6 +38,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.util.UrlPathHelper; @@ -79,8 +80,10 @@ public class HandlerMethodMappingTests { String key = "foo"; this.mapping.registerMapping(key, this.handler, this.method1); - HandlerMethod result = this.mapping.getHandlerInternal(new MockHttpServletRequest("GET", key)); + MockHttpServletRequest request = new MockHttpServletRequest("GET", key); + HandlerMethod result = this.mapping.getHandlerInternal(request); assertEquals(method1, result.getMethod()); + assertEquals(result, request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)); } @Test @@ -88,8 +91,10 @@ public class HandlerMethodMappingTests { this.mapping.registerMapping("/fo*", this.handler, this.method1); this.mapping.registerMapping("/f*", this.handler, this.method2); - HandlerMethod result = this.mapping.getHandlerInternal(new MockHttpServletRequest("GET", "/foo")); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + HandlerMethod result = this.mapping.getHandlerInternal(request); assertEquals(method1, result.getMethod()); + assertEquals(result, request.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)); } @Test(expected = IllegalStateException.class) diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java index dd6b09bd..2550405d 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java @@ -41,17 +41,18 @@ import static org.junit.Assert.*; public class SimpleUrlHandlerMappingTests { @Test - public void handlerBeanNotFound() throws Exception { + @SuppressWarnings("resource") + public void handlerBeanNotFound() { MockServletContext sc = new MockServletContext(""); XmlWebApplicationContext root = new XmlWebApplicationContext(); root.setServletContext(sc); - root.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map1.xml"}); + root.setConfigLocations("/org/springframework/web/servlet/handler/map1.xml"); root.refresh(); XmlWebApplicationContext wac = new XmlWebApplicationContext(); wac.setParent(root); wac.setServletContext(sc); wac.setNamespace("map2err"); - wac.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map2err.xml"}); + wac.setConfigLocations("/org/springframework/web/servlet/handler/map2err.xml"); try { wac.refresh(); fail("Should have thrown NoSuchBeanDefinitionException"); @@ -93,7 +94,7 @@ public class SimpleUrlHandlerMappingTests { MockServletContext sc = new MockServletContext(""); XmlWebApplicationContext wac = new XmlWebApplicationContext(); wac.setServletContext(sc); - wac.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map2.xml"}); + wac.setConfigLocations("/org/springframework/web/servlet/handler/map2.xml"); wac.refresh(); Object bean = wac.getBean("mainController"); Object otherBean = wac.getBean("otherController"); @@ -104,11 +105,13 @@ public class SimpleUrlHandlerMappingTests { HandlerExecutionChain hec = getHandler(hm, req); assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean); assertEquals("/welcome.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)); + assertEquals(bean, req.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)); req = new MockHttpServletRequest("GET", "/welcome.x"); hec = getHandler(hm, req); assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean); assertEquals("welcome.x", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)); + assertEquals(otherBean, req.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE)); req = new MockHttpServletRequest("GET", "/welcome/"); hec = getHandler(hm, req); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilterTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilterTests.java index d7716c7d..7722f763 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilterTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilterTests.java @@ -38,7 +38,7 @@ public class ResourceUrlEncodingFilterTests { private ResourceUrlEncodingFilter filter; - private ResourceUrlProvider resourceUrlProvider; + private ResourceUrlProvider urlProvider; @Before public void createFilter() throws Exception { @@ -49,16 +49,16 @@ public class ResourceUrlEncodingFilterTests { List<ResourceResolver> resolvers = Arrays.asList(versionResolver, pathResolver); this.filter = new ResourceUrlEncodingFilter(); - this.resourceUrlProvider = createResourceUrlProvider(resolvers); + this.urlProvider = createResourceUrlProvider(resolvers); } @Test public void encodeURL() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("/resources/bar.css"); assertEquals("/resources/bar-11e16cf79faee7ac698c805cf28248d2.css", result); }); @@ -68,10 +68,26 @@ public class ResourceUrlEncodingFilterTests { public void encodeURLWithContext() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context/foo"); request.setContextPath("/context"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); + String result = ((HttpServletResponse) res).encodeURL("/context/resources/bar.css"); + assertEquals("/context/resources/bar-11e16cf79faee7ac698c805cf28248d2.css", result); + }); + } + + + @Test + public void encodeUrlWithContextAndForwardedRequest() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context/foo"); + request.setContextPath("/context"); + MockHttpServletResponse response = new MockHttpServletResponse(); + + this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); + request.setRequestURI("/forwarded"); + request.setContextPath("/"); String result = ((HttpServletResponse) res).encodeURL("/context/resources/bar.css"); assertEquals("/context/resources/bar-11e16cf79faee7ac698c805cf28248d2.css", result); }); @@ -82,10 +98,10 @@ public class ResourceUrlEncodingFilterTests { public void encodeContextPathUrlWithoutSuffix() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context"); request.setContextPath("/context"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("/context/resources/bar.css"); assertEquals("/context/resources/bar-11e16cf79faee7ac698c805cf28248d2.css", result); }); @@ -95,10 +111,10 @@ public class ResourceUrlEncodingFilterTests { public void encodeContextPathUrlWithSuffix() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context/"); request.setContextPath("/context"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("/context/resources/bar.css"); assertEquals("/context/resources/bar-11e16cf79faee7ac698c805cf28248d2.css", result); }); @@ -109,10 +125,10 @@ public class ResourceUrlEncodingFilterTests { public void encodeEmptyURLWithContext() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context/foo"); request.setContextPath("/context"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("?foo=1"); assertEquals("?foo=1", result); }); @@ -123,10 +139,10 @@ public class ResourceUrlEncodingFilterTests { public void encodeURLWithRequestParams() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); request.setContextPath("/"); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("/resources/bar.css?foo=bar&url=http://example.org"); assertEquals("/resources/bar-11e16cf79faee7ac698c805cf28248d2.css?foo=bar&url=http://example.org", result); }); @@ -138,10 +154,10 @@ public class ResourceUrlEncodingFilterTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context-path/index"); request.setContextPath("/context-path"); request.setServletPath(""); - request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); MockHttpServletResponse response = new MockHttpServletResponse(); this.filter.doFilter(request, response, (req, res) -> { + req.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.urlProvider); String result = ((HttpServletResponse) res).encodeURL("index?key=value"); assertEquals("index?key=value", result); }); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderJavaConfigTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderJavaConfigTests.java index 9ad2f6aa..fbdc0f5c 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderJavaConfigTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderJavaConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2018 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. @@ -16,6 +16,14 @@ package org.springframework.web.servlet.resource; +import java.io.IOException; +import java.util.Arrays; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -23,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Test; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.test.MockFilterChain; import org.springframework.mock.web.test.MockHttpServletRequest; @@ -55,8 +64,6 @@ public class ResourceUrlProviderJavaConfigTests { @Before @SuppressWarnings("resource") public void setup() throws Exception { - this.filterChain = new MockFilterChain(this.servlet, new ResourceUrlEncodingFilter()); - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.setServletContext(new MockServletContext()); context.register(WebConfig.class); @@ -66,8 +73,9 @@ public class ResourceUrlProviderJavaConfigTests { this.request.setContextPath("/myapp"); this.response = new MockHttpServletResponse(); - Object urlProvider = context.getBean(ResourceUrlProvider.class); - this.request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, urlProvider); + this.filterChain = new MockFilterChain(this.servlet, + new ResourceUrlEncodingFilter(), + new ResourceUrlProviderExposingFilter(context)); } @Test @@ -117,6 +125,34 @@ public class ResourceUrlProviderJavaConfigTests { } @SuppressWarnings("serial") + private static class ResourceUrlProviderExposingFilter implements Filter { + + private final ApplicationContext context; + + public ResourceUrlProviderExposingFilter(ApplicationContext context) { + this.context = context; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + Object urlProvider = context.getBean(ResourceUrlProvider.class); + request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, urlProvider); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + } + + @SuppressWarnings("serial") private static class TestServlet extends HttpServlet { private HttpServletResponse wrappedResponse; |