Add empty location check to ResourceHttpRequestHandler
ResourceHttpRequestHandler now implements InitializingBean and checks for empty locations. Issue: SPR-9186
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user