提交 24d77f32 编写于 作者: R Rossen Stoyanchev

Prepend leading slash in ResourceUrlProvider

The getForRequestUrl method of ResourceUrlProvider uses the
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE attribute to
determine the relevant portion of the resource URL path.

However there are cases when that attribute may not have a leading
(e.g. when the current URL was matched to a prefix-based pattern
and hence extracted via PathMatcher#extractPathWithinPattern), which
interferes with the matching of resource URL paths to patterns.

This change ensures a leading slash is present

Issue: SPR-12281
上级 fa4ba2a8
...@@ -179,6 +179,9 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed ...@@ -179,6 +179,9 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
pathWithinMapping = getPathHelper().getLookupPathForRequest(request); pathWithinMapping = getPathHelper().getLookupPathForRequest(request);
} }
// When extracted with PathMatcher, pathWithinMapping won't have leading slash
pathWithinMapping = (pathWithinMapping.charAt(0) == '/' ? pathWithinMapping : "/" + pathWithinMapping);
int index = getPathHelper().getRequestUri(request).indexOf(pathWithinMapping); int index = getPathHelper().getRequestUri(request).indexOf(pathWithinMapping);
Assert.state(index != -1, "Failed to determine lookup path: " + requestUrl); Assert.state(index != -1, "Failed to determine lookup path: " + requestUrl);
......
...@@ -69,7 +69,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -69,7 +69,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void getResource() throws Exception { public void getResource() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals("text/css", this.response.getContentType()); assertEquals("text/css", this.response.getContentType());
...@@ -83,7 +83,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -83,7 +83,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void getResourceWithHtmlMediaType() throws Exception { public void getResourceWithHtmlMediaType() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.html"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.html");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals("text/html", this.response.getContentType()); assertEquals("text/html", this.response.getContentType());
...@@ -95,7 +95,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -95,7 +95,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void getResourceFromAlternatePath() throws Exception { public void getResourceFromAlternatePath() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/baz.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "baz.css");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals("text/css", this.response.getContentType()); assertEquals("text/css", this.response.getContentType());
...@@ -109,7 +109,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -109,7 +109,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void getResourceFromSubDirectory() throws Exception { public void getResourceFromSubDirectory() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/js/foo.js"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/foo.js");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals("text/javascript", this.response.getContentType()); assertEquals("text/javascript", this.response.getContentType());
...@@ -118,7 +118,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -118,7 +118,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void getResourceFromSubDirectoryOfAlternatePath() throws Exception { public void getResourceFromSubDirectoryOfAlternatePath() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/js/baz.js"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/baz.js");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals("text/javascript", this.response.getContentType()); assertEquals("text/javascript", this.response.getContentType());
...@@ -147,7 +147,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -147,7 +147,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void notModified() throws Exception { public void notModified() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.request.addHeader("If-Modified-Since", resourceLastModified("test/foo.css")); this.request.addHeader("If-Modified-Since", resourceLastModified("test/foo.css"));
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals(HttpServletResponse.SC_NOT_MODIFIED, this.response.getStatus()); assertEquals(HttpServletResponse.SC_NOT_MODIFIED, this.response.getStatus());
...@@ -155,7 +155,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -155,7 +155,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void modified() throws Exception { public void modified() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.request.addHeader("If-Modified-Since", resourceLastModified("test/foo.css") / 1000 * 1000 - 1); this.request.addHeader("If-Modified-Since", resourceLastModified("test/foo.css") / 1000 * 1000 - 1);
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals(HttpServletResponse.SC_OK, this.response.getStatus()); assertEquals(HttpServletResponse.SC_OK, this.response.getStatus());
...@@ -164,7 +164,7 @@ public class ResourceHttpRequestHandlerTests { ...@@ -164,7 +164,7 @@ public class ResourceHttpRequestHandlerTests {
@Test @Test
public void directory() throws Exception { public void directory() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/js/"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals(404, this.response.getStatus()); assertEquals(404, this.response.getStatus());
} }
...@@ -183,14 +183,14 @@ public class ResourceHttpRequestHandlerTests { ...@@ -183,14 +183,14 @@ public class ResourceHttpRequestHandlerTests {
@Test(expected=HttpRequestMethodNotSupportedException.class) @Test(expected=HttpRequestMethodNotSupportedException.class)
public void unsupportedHttpMethod() throws Exception { public void unsupportedHttpMethod() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.request.setMethod("POST"); this.request.setMethod("POST");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
} }
@Test @Test
public void resourceNotFound() throws Exception { public void resourceNotFound() throws Exception {
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/not-there.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "not-there.css");
this.handler.handleRequest(this.request, this.response); this.handler.handleRequest(this.request, this.response);
assertEquals(404, this.response.getStatus()); assertEquals(404, this.response.getStatus());
} }
......
...@@ -72,7 +72,7 @@ public class ResourceTransformerSupportTests { ...@@ -72,7 +72,7 @@ public class ResourceTransformerSupportTests {
@Test @Test
public void resolveUrlPath() throws Exception { public void resolveUrlPath() throws Exception {
this.request.setRequestURI("/context/servlet/resources/main.css"); this.request.setRequestURI("/context/servlet/resources/main.css");
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/resources/main.css"); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "resources/main.css");
String resourcePath = "/context/servlet/resources/bar.css"; String resourcePath = "/context/servlet/resources/bar.css";
Resource css = new ClassPathResource("test/main.css", getClass()); Resource css = new ClassPathResource("test/main.css", getClass());
......
...@@ -28,6 +28,7 @@ import org.springframework.mock.web.test.MockHttpServletRequest; ...@@ -28,6 +28,7 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockServletContext; import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.config.annotation.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
...@@ -68,7 +69,6 @@ public class ResourceUrlProviderJavaConfigTests { ...@@ -68,7 +69,6 @@ public class ResourceUrlProviderJavaConfigTests {
this.request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, urlProvider); this.request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, urlProvider);
} }
@Test @Test
public void resolvePathWithRootServletMapping() throws Exception { public void resolvePathWithRootServletMapping() throws Exception {
this.request.setRequestURI("/myapp/index"); this.request.setRequestURI("/myapp/index");
...@@ -99,6 +99,19 @@ public class ResourceUrlProviderJavaConfigTests { ...@@ -99,6 +99,19 @@ public class ResourceUrlProviderJavaConfigTests {
resolvePublicResourceUrlPath("/myapp/resources/foo.css")); resolvePublicResourceUrlPath("/myapp/resources/foo.css"));
} }
// SPR-12281
@Test
public void resolvePathWithHandlerMappingAttribute() throws Exception {
this.request.setRequestURI("/myapp/index");
this.request.setServletPath("/index");
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "index");
this.filterChain.doFilter(this.request, this.response);
assertEquals("/myapp/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css",
resolvePublicResourceUrlPath("/myapp/resources/foo.css"));
}
private String resolvePublicResourceUrlPath(String path) { private String resolvePublicResourceUrlPath(String path) {
return this.servlet.wrappedResponse.encodeURL(path); return this.servlet.wrappedResponse.encodeURL(path);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册