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 e50a48e812..f36ac7b649 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 @@ -115,7 +115,7 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean { return null; } if (this.indexLookupPath != null && url.startsWith(this.prefixLookupPath)) { - int suffixIndex = getQueryParamsIndex(url); + int suffixIndex = getEndPathIndex(url); String suffix = url.substring(suffixIndex); String lookupPath = url.substring(this.indexLookupPath, suffixIndex); lookupPath = this.resourceUrlProvider.getForLookupPath(lookupPath); @@ -126,9 +126,17 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean { return null; } - private int getQueryParamsIndex(String url) { - int index = url.indexOf('?'); - return (index > 0 ? index : url.length()); + private int getEndPathIndex(String lookupPath) { + int suffixIndex = lookupPath.length(); + int queryIndex = lookupPath.indexOf('?'); + if (queryIndex > 0) { + suffixIndex = queryIndex; + } + int hashIndex = lookupPath.indexOf('#'); + if (hashIndex > 0) { + suffixIndex = Math.min(suffixIndex, hashIndex); + } + return suffixIndex; } } 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 b704445c42..c24b830bc3 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 @@ -173,4 +173,30 @@ public class ResourceUrlEncodingFilterTests { }); } + @Test // SPR-17535 + public void encodeURLWitFragment() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.setContextPath("/"); + 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#something"); + assertEquals("/resources/bar-11e16cf79faee7ac698c805cf28248d2.css#something", result); + }); + } + + @Test // SPR-13374 and SPR-17535 combined + public void encodeURLWitFragmentAndRequestParams() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.setContextPath("/"); + 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#something"); + assertEquals("/resources/bar-11e16cf79faee7ac698c805cf28248d2.css?foo=bar&url=http://example.org#something", result); + }); + } + }