Browse Source

Add empty location check to ResourceHttpRequestHandler

ResourceHttpRequestHandler now implements InitializingBean and
checks for empty locations.

Issue: SPR-9186
pull/72/head
Rossen Stoyanchev 14 years ago
parent
commit
1eaaa9a446
  1. 10
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
  2. 37
      spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

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

@ -25,6 +25,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -38,7 +39,7 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.support.WebContentGenerator; import org.springframework.web.servlet.support.WebContentGenerator;
/** /**
* {@link HttpRequestHandler} that serves static resources optimized for superior browser performance * {@link HttpRequestHandler} that serves static resources optimized for superior browser performance
* (according to the guidelines of Page Speed, YSlow, etc.) by allowing for flexible cache settings * (according to the guidelines of Page Speed, YSlow, etc.) by allowing for flexible cache settings
* ({@linkplain #setCacheSeconds "cacheSeconds" property}, last-modified support). * ({@linkplain #setCacheSeconds "cacheSeconds" property}, last-modified support).
* *
@ -50,7 +51,7 @@ import org.springframework.web.servlet.support.WebContentGenerator;
* (if present) so that a {@code 304} status code will be returned as appropriate, avoiding unnecessary * (if present) so that a {@code 304} status code will be returned as appropriate, avoiding unnecessary
* overhead for resources that are already cached by the client. The use of {@code Resource} locations * overhead for resources that are already cached by the client. The use of {@code Resource} locations
* allows resource requests to easily be mapped to locations other than the web application root. For * allows resource requests to easily be mapped to locations other than the web application root. For
* example, resources could be served from a classpath location such as "classpath:/META-INF/public-web-resources/", * example, resources could be served from a classpath location such as "classpath:/META-INF/public-web-resources/",
* allowing convenient packaging and serving of resources such as a JavaScript library from within jar files. * allowing convenient packaging and serving of resources such as a JavaScript library from within jar files.
* *
* <p>To ensure that users with a primed browser cache get the latest changes to application-specific * <p>To ensure that users with a primed browser cache get the latest changes to application-specific
@ -66,7 +67,7 @@ import org.springframework.web.servlet.support.WebContentGenerator;
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 3.0.4 * @since 3.0.4
*/ */
public class ResourceHttpRequestHandler extends WebContentGenerator implements HttpRequestHandler { public class ResourceHttpRequestHandler extends WebContentGenerator implements HttpRequestHandler, InitializingBean {
private static final boolean jafPresent = private static final boolean jafPresent =
ClassUtils.isPresent("javax.activation.FileTypeMap", ResourceHttpRequestHandler.class.getClassLoader()); ClassUtils.isPresent("javax.activation.FileTypeMap", ResourceHttpRequestHandler.class.getClassLoader());
@ -87,6 +88,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator implements H
this.locations = locations; this.locations = locations;
} }
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(locations, "Locations list must not be empty");
}
/** /**
* Processes a resource request. * Processes a resource request.

37
spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

@ -41,7 +41,7 @@ import static org.junit.Assert.*;
public class ResourceHttpRequestHandlerTests { public class ResourceHttpRequestHandlerTests {
private ResourceHttpRequestHandler handler; private ResourceHttpRequestHandler handler;
@Before @Before
public void setUp() { public void setUp() {
List<Resource> resourcePaths = new ArrayList<Resource>(); List<Resource> resourcePaths = new ArrayList<Resource>();
@ -52,7 +52,7 @@ public class ResourceHttpRequestHandlerTests {
handler.setCacheSeconds(3600); handler.setCacheSeconds(3600);
handler.setServletContext(new TestServletContext()); handler.setServletContext(new TestServletContext());
} }
@Test @Test
public void getResource() throws Exception { public void getResource() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -65,11 +65,11 @@ public class ResourceHttpRequestHandlerTests {
assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000)); assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000));
assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control")); assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control"));
assertTrue(response.containsHeader("Last-Modified")); assertTrue(response.containsHeader("Last-Modified"));
assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(), assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(),
new ClassPathResource("test/foo.css", getClass()).getFile().lastModified()); new ClassPathResource("test/foo.css", getClass()).getFile().lastModified());
assertEquals("h1 { color:red; }", response.getContentAsString()); assertEquals("h1 { color:red; }", response.getContentAsString());
} }
@Test @Test
public void getResourceWithHtmlMediaType() throws Exception { public void getResourceWithHtmlMediaType() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -81,10 +81,10 @@ public class ResourceHttpRequestHandlerTests {
assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000)); assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000));
assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control")); assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control"));
assertTrue(response.containsHeader("Last-Modified")); assertTrue(response.containsHeader("Last-Modified"));
assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(), assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(),
new ClassPathResource("test/foo.html", getClass()).getFile().lastModified()); new ClassPathResource("test/foo.html", getClass()).getFile().lastModified());
} }
@Test @Test
public void getResourceFromAlternatePath() throws Exception { public void getResourceFromAlternatePath() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -97,11 +97,11 @@ public class ResourceHttpRequestHandlerTests {
assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000)); assertTrue(Long.valueOf(response.getHeader("Expires")) >= System.currentTimeMillis() - 1000 + (3600 * 1000));
assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control")); assertEquals("max-age=3600, must-revalidate", response.getHeader("Cache-Control"));
assertTrue(response.containsHeader("Last-Modified")); assertTrue(response.containsHeader("Last-Modified"));
assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(), assertEquals(Long.valueOf(response.getHeader("Last-Modified")).longValue(),
new ClassPathResource("testalternatepath/baz.css", getClass()).getFile().lastModified()); new ClassPathResource("testalternatepath/baz.css", getClass()).getFile().lastModified());
assertEquals("h1 { color:red; }", response.getContentAsString()); assertEquals("h1 { color:red; }", response.getContentAsString());
} }
@Test @Test
public void getResourceFromSubDirectory() throws Exception { public void getResourceFromSubDirectory() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -112,7 +112,7 @@ public class ResourceHttpRequestHandlerTests {
assertEquals("text/javascript", response.getContentType()); assertEquals("text/javascript", response.getContentType());
assertEquals("function foo() { console.log(\"hello world\"); }", response.getContentAsString()); assertEquals("function foo() { console.log(\"hello world\"); }", response.getContentAsString());
} }
@Test @Test
public void getResourceFromSubDirectoryOfAlternatePath() throws Exception { public void getResourceFromSubDirectoryOfAlternatePath() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -138,7 +138,7 @@ public class ResourceHttpRequestHandlerTests {
response = new MockHttpServletResponse(); response = new MockHttpServletResponse();
handler.handleRequest(request, response); handler.handleRequest(request, response);
assertEquals(404, response.getStatus()); assertEquals(404, response.getStatus());
handler.setLocations(Arrays.<Resource>asList(new ClassPathResource("testsecret/", getClass()))); handler.setLocations(Arrays.<Resource>asList(new ClassPathResource("testsecret/", getClass())));
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "secret.txt"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "secret.txt");
response = new MockHttpServletResponse(); response = new MockHttpServletResponse();
@ -158,7 +158,7 @@ public class ResourceHttpRequestHandlerTests {
handler.handleRequest(request, response); handler.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatus()); assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatus());
} }
@Test @Test
public void modified() throws Exception { public void modified() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -169,9 +169,9 @@ public class ResourceHttpRequestHandlerTests {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
handler.handleRequest(request, response); handler.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus()); assertEquals(HttpServletResponse.SC_OK, response.getStatus());
assertEquals("h1 { color:red; }", response.getContentAsString()); assertEquals("h1 { color:red; }", response.getContentAsString());
} }
@Test @Test
public void directory() throws Exception { public void directory() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -191,7 +191,7 @@ public class ResourceHttpRequestHandlerTests {
handler.handleRequest(request, response); handler.handleRequest(request, response);
assertEquals(404, response.getStatus()); assertEquals(404, response.getStatus());
} }
@Test(expected=IllegalStateException.class) @Test(expected=IllegalStateException.class)
public void noPathWithinHandlerMappingAttribute() throws Exception { public void noPathWithinHandlerMappingAttribute() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -199,7 +199,7 @@ public class ResourceHttpRequestHandlerTests {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
handler.handleRequest(request, response); handler.handleRequest(request, response);
} }
@Test(expected=HttpRequestMethodNotSupportedException.class) @Test(expected=HttpRequestMethodNotSupportedException.class)
public void unsupportedHttpMethod() throws Exception { public void unsupportedHttpMethod() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -208,7 +208,7 @@ public class ResourceHttpRequestHandlerTests {
MockHttpServletResponse response = new MockHttpServletResponse(); MockHttpServletResponse response = new MockHttpServletResponse();
handler.handleRequest(request, response); handler.handleRequest(request, response);
} }
@Test @Test
public void resourceNotFound() throws Exception { public void resourceNotFound() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
@ -219,6 +219,11 @@ public class ResourceHttpRequestHandlerTests {
assertEquals(404, response.getStatus()); assertEquals(404, response.getStatus());
} }
@Test(expected=IllegalArgumentException.class)
public void locationsNotSet() throws Exception {
new ResourceHttpRequestHandler().afterPropertiesSet();
}
private static class TestServletContext extends MockServletContext { private static class TestServletContext extends MockServletContext {

Loading…
Cancel
Save