diff options
Diffstat (limited to 'spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java')
-rw-r--r-- | spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java | 207 |
1 files changed, 154 insertions, 53 deletions
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java index 453bdbdc..c78f7573 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java @@ -16,20 +16,14 @@ package org.springframework.web.servlet.resource; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; - -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.TimeZone; - import javax.servlet.http.HttpServletResponse; import org.hamcrest.Matchers; @@ -39,19 +33,27 @@ import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockServletContext; import org.springframework.util.StringUtils; import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.accept.ContentNegotiationManager; +import org.springframework.web.accept.ContentNegotiationManagerFactoryBean; import org.springframework.web.servlet.HandlerMapping; +import static org.junit.Assert.*; + /** * Unit tests for ResourceHttpRequestHandler. * * @author Keith Donald * @author Jeremy Grelle * @author Rossen Stoyanchev + * @author Brian Clozel */ public class ResourceHttpRequestHandlerTests { @@ -94,10 +96,39 @@ public class ResourceHttpRequestHandlerTests { assertEquals("max-age=3600", this.response.getHeader("Cache-Control")); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); assertEquals("h1 { color:red; }", this.response.getContentAsString()); } @Test + public void getResourceHttpHeader() throws Exception { + this.request.setMethod("HEAD"); + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.handler.handleRequest(this.request, this.response); + + assertEquals(200, this.response.getStatus()); + assertEquals("text/css", this.response.getContentType()); + assertEquals(17, this.response.getContentLength()); + assertEquals("max-age=3600", this.response.getHeader("Cache-Control")); + assertTrue(this.response.containsHeader("Last-Modified")); + assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); + assertEquals(0, this.response.getContentAsByteArray().length); + } + + @Test + public void getResourceHttpOptions() throws Exception { + this.request.setMethod("OPTIONS"); + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.handler.handleRequest(this.request, this.response); + + assertEquals(200, this.response.getStatus()); + assertEquals("GET,HEAD,OPTIONS", this.response.getHeader("Allow")); + } + + @Test public void getResourceNoCache() throws Exception { this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); this.handler.setCacheSeconds(0); @@ -106,6 +137,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals("no-store", this.response.getHeader("Cache-Control")); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -119,6 +152,8 @@ public class ResourceHttpRequestHandlerTests { this.handler.handleRequest(this.request, this.response); assertEquals("\"versionString\"", this.response.getHeader("ETag")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -135,6 +170,8 @@ public class ResourceHttpRequestHandlerTests { assertTrue(dateHeaderAsLong("Expires") >= System.currentTimeMillis() - 1000 + (3600 * 1000)); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.css")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -153,6 +190,8 @@ public class ResourceHttpRequestHandlerTests { assertTrue(dateHeaderAsLong("Expires") <= System.currentTimeMillis()); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(dateHeaderAsLong("Last-Modified") / 1000, resourceLastModified("test/foo.css") / 1000); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -164,6 +203,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals("max-age=3600", this.response.getHeader("Cache-Control")); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("test/foo.html")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -176,6 +217,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals("max-age=3600", this.response.getHeader("Cache-Control")); assertTrue(this.response.containsHeader("Last-Modified")); assertEquals(this.response.getHeader("Last-Modified"), resourceLastModifiedDate("testalternatepath/baz.css")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); assertEquals("h1 { color:red; }", this.response.getContentAsString()); } @@ -197,18 +240,96 @@ public class ResourceHttpRequestHandlerTests { assertEquals("function foo() { console.log(\"hello world\"); }", this.response.getContentAsString()); } + @Test // SPR-13658 + public void getResourceWithRegisteredMediaType() throws Exception { + ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean(); + factory.addMediaType("css", new MediaType("foo", "bar")); + factory.afterPropertiesSet(); + ContentNegotiationManager manager = factory.getObject(); + + List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); + this.handler = new ResourceHttpRequestHandler(); + this.handler.setLocations(paths); + this.handler.setContentNegotiationManager(manager); + this.handler.afterPropertiesSet(); + + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.handler.handleRequest(this.request, this.response); + + assertEquals("foo/bar", this.response.getContentType()); + assertEquals("h1 { color:red; }", this.response.getContentAsString()); + } + + @Test // SPR-13658 + public void getResourceWithRegisteredMediaTypeDefaultStrategy() throws Exception { + ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean(); + factory.setFavorPathExtension(false); + factory.setDefaultContentType(new MediaType("foo", "bar")); + factory.afterPropertiesSet(); + ContentNegotiationManager manager = factory.getObject(); + + List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); + this.handler = new ResourceHttpRequestHandler(); + this.handler.setLocations(paths); + this.handler.setContentNegotiationManager(manager); + this.handler.afterPropertiesSet(); + + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.handler.handleRequest(this.request, this.response); + + assertEquals("foo/bar", this.response.getContentType()); + assertEquals("h1 { color:red; }", this.response.getContentAsString()); + } + + @Test // SPR-14368 + public void getResourceWithMediaTypeResolvedThroughServletContext() throws Exception { + MockServletContext servletContext = new MockServletContext() { + + @Override + public String getMimeType(String filePath) { + return "foo/bar"; + } + + @Override + public String getVirtualServerName() { + return null; + } + }; + + List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); + this.handler = new ResourceHttpRequestHandler(); + this.handler.setServletContext(servletContext); + this.handler.setLocations(paths); + this.handler.afterPropertiesSet(); + + this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); + this.handler.handleRequest(this.request, this.response); + + assertEquals("foo/bar", this.response.getContentType()); + assertEquals("h1 { color:red; }", this.response.getContentAsString()); + } + @Test public void invalidPath() throws Exception { + for (HttpMethod method : HttpMethod.values()) { + this.request = new MockHttpServletRequest("GET", ""); + this.response = new MockHttpServletResponse(); + testInvalidPath(method); + } + } + + private void testInvalidPath(HttpMethod httpMethod) throws Exception { + this.request.setMethod(httpMethod.name()); Resource location = new ClassPathResource("test/", getClass()); - this.handler.setLocations(Arrays.asList(location)); + this.handler.setLocations(Collections.singletonList(location)); testInvalidPath(location, "../testsecret/secret.txt"); testInvalidPath(location, "test/../../testsecret/secret.txt"); testInvalidPath(location, ":/../../testsecret/secret.txt"); location = new UrlResource(getClass().getResource("./test/")); - this.handler.setLocations(Arrays.asList(location)); + this.handler.setLocations(Collections.singletonList(location)); Resource secretResource = new UrlResource(getClass().getResource("testsecret/secret.txt")); String secretPath = secretResource.getURL().getPath(); @@ -230,7 +351,7 @@ public class ResourceHttpRequestHandlerTests { if (!location.createRelative(requestPath).exists() && !requestPath.contains(":")) { fail(requestPath + " doesn't actually exist as a relative path"); } - assertEquals(404, this.response.getStatus()); + assertEquals(HttpStatus.NOT_FOUND.value(), this.response.getStatus()); } @Test @@ -290,7 +411,7 @@ public class ResourceHttpRequestHandlerTests { pathResolver.setAllowedLocations(location1); ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); - handler.setResourceResolvers(Arrays.asList(pathResolver)); + handler.setResourceResolvers(Collections.singletonList(pathResolver)); handler.setLocations(Arrays.asList(location1, location2)); handler.afterPropertiesSet(); @@ -352,9 +473,18 @@ public class ResourceHttpRequestHandlerTests { @Test public void resourceNotFound() throws Exception { + for (HttpMethod method : HttpMethod.values()) { + this.request = new MockHttpServletRequest("GET", ""); + this.response = new MockHttpServletResponse(); + resourceNotFound(method); + } + } + + private void resourceNotFound(HttpMethod httpMethod) throws Exception { + this.request.setMethod(httpMethod.name()); this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "not-there.css"); this.handler.handleRequest(this.request, this.response); - assertEquals(404, this.response.getStatus()); + assertEquals(HttpStatus.NOT_FOUND.value(), this.response.getStatus()); } @Test @@ -368,6 +498,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(2, this.response.getContentLength()); assertEquals("bytes 0-1/10", this.response.getHeader("Content-Range")); assertEquals("So", this.response.getContentAsString()); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -381,6 +513,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(1, this.response.getContentLength()); assertEquals("bytes 9-9/10", this.response.getHeader("Content-Range")); assertEquals(".", this.response.getContentAsString()); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -394,6 +528,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(1, this.response.getContentLength()); assertEquals("bytes 9-9/10", this.response.getHeader("Content-Range")); assertEquals(".", this.response.getContentAsString()); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -407,6 +543,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(1, this.response.getContentLength()); assertEquals("bytes 9-9/10", this.response.getHeader("Content-Range")); assertEquals(".", this.response.getContentAsString()); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -420,6 +558,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(10, this.response.getContentLength()); assertEquals("bytes 0-9/10", this.response.getHeader("Content-Range")); assertEquals("Some text.", this.response.getContentAsString()); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -430,6 +570,8 @@ public class ResourceHttpRequestHandlerTests { assertEquals(416, this.response.getStatus()); assertEquals("bytes */10", this.response.getHeader("Content-Range")); + assertEquals("bytes", this.response.getHeader("Accept-Ranges")); + assertEquals(1, this.response.getHeaders("Accept-Ranges").size()); } @Test @@ -462,47 +604,6 @@ public class ResourceHttpRequestHandlerTests { assertEquals("t.", ranges[11]); } - // SPR-12999 - @Test - public void writeContentNotGettingInputStream() throws Exception { - Resource resource = mock(Resource.class); - given(resource.getInputStream()).willThrow(FileNotFoundException.class); - - this.handler.writeContent(this.response, resource); - - assertEquals(200, this.response.getStatus()); - assertEquals(0, this.response.getContentLength()); - } - - // SPR-12999 - @Test - public void writeContentNotClosingInputStream() throws Exception { - Resource resource = mock(Resource.class); - InputStream inputStream = mock(InputStream.class); - given(resource.getInputStream()).willReturn(inputStream); - given(inputStream.read(any())).willReturn(-1); - doThrow(new NullPointerException()).when(inputStream).close(); - - this.handler.writeContent(this.response, resource); - - assertEquals(200, this.response.getStatus()); - assertEquals(0, this.response.getContentLength()); - } - - // SPR-13620 - @Test - public void writeContentInputStreamThrowingNullPointerException() throws Exception { - Resource resource = mock(Resource.class); - InputStream in = mock(InputStream.class); - given(resource.getInputStream()).willReturn(in); - given(in.read(any())).willThrow(NullPointerException.class); - - this.handler.writeContent(this.response, resource); - - assertEquals(200, this.response.getStatus()); - assertEquals(0, this.response.getContentLength()); - } - // SPR-14005 @Test public void doOverwriteExistingCacheControlHeaders() throws Exception { |