|
|
|
|
@ -17,8 +17,6 @@
@@ -17,8 +17,6 @@
|
|
|
|
|
package org.springframework.web.servlet.resource; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
|
|
@ -61,7 +59,7 @@ import static org.mockito.Mockito.mock;
@@ -61,7 +59,7 @@ import static org.mockito.Mockito.mock;
|
|
|
|
|
* @author Sam Brannen |
|
|
|
|
*/ |
|
|
|
|
@ExtendWith(GzipSupport.class) |
|
|
|
|
public class ResourceHttpRequestHandlerTests { |
|
|
|
|
class ResourceHttpRequestHandlerTests { |
|
|
|
|
|
|
|
|
|
private final ClassPathResource testResource = new ClassPathResource("test/", getClass()); |
|
|
|
|
private final ClassPathResource testAlternatePathResource = new ClassPathResource("testalternatepath/", getClass()); |
|
|
|
|
@ -75,7 +73,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -75,7 +73,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeEach |
|
|
|
|
public void setup() throws Exception { |
|
|
|
|
void setup() throws Exception { |
|
|
|
|
List<Resource> locations = List.of( |
|
|
|
|
this.testResource, |
|
|
|
|
this.testAlternatePathResource, |
|
|
|
|
@ -95,7 +93,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -95,7 +93,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResource() throws Exception { |
|
|
|
|
void getResource() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
|
|
|
|
|
@ -105,12 +103,12 @@ public class ResourceHttpRequestHandlerTests {
@@ -105,12 +103,12 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("test/foo.css") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("h1 { color:red; }"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceHttpHeader() throws Exception { |
|
|
|
|
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); |
|
|
|
|
@ -127,7 +125,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -127,7 +125,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceHttpOptions() throws Exception { |
|
|
|
|
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); |
|
|
|
|
@ -137,7 +135,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -137,7 +135,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceNoCache() throws Exception { |
|
|
|
|
void getResourceNoCache() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.handler.setCacheSeconds(0); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -146,14 +144,14 @@ public class ResourceHttpRequestHandlerTests {
@@ -146,14 +144,14 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("test/foo.css") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getVersionedResource() throws Exception { |
|
|
|
|
void getVersionedResource() throws Exception { |
|
|
|
|
VersionResourceResolver versionResolver = new VersionResourceResolver() |
|
|
|
|
.addFixedVersionStrategy("versionString", "/**"); |
|
|
|
|
this.handler.setResourceResolvers(Arrays.asList(versionResolver, new PathResourceResolver())); |
|
|
|
|
this.handler.setResourceResolvers(List.of(versionResolver, new PathResourceResolver())); |
|
|
|
|
this.handler.afterPropertiesSet(); |
|
|
|
|
|
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "versionString/foo.css"); |
|
|
|
|
@ -161,12 +159,12 @@ public class ResourceHttpRequestHandlerTests {
@@ -161,12 +159,12 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
|
|
|
|
|
assertThat(this.response.getHeader("ETag")).isEqualTo("W/\"versionString\""); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
@SuppressWarnings("deprecation") |
|
|
|
|
public void getResourceHttp10BehaviorCache() throws Exception { |
|
|
|
|
void getResourceHttp10BehaviorCache() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.handler.setCacheSeconds(3600); |
|
|
|
|
this.handler.setUseExpiresHeader(true); |
|
|
|
|
@ -179,12 +177,12 @@ public class ResourceHttpRequestHandlerTests {
@@ -179,12 +177,12 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("test/foo.css") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
@SuppressWarnings("deprecation") |
|
|
|
|
public void getResourceHttp10BehaviorNoCache() throws Exception { |
|
|
|
|
void getResourceHttp10BehaviorNoCache() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.handler.setCacheSeconds(0); |
|
|
|
|
this.handler.setUseExpiresHeader(true); |
|
|
|
|
@ -199,11 +197,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -199,11 +197,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("test/foo.css") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceWithHtmlMediaType() throws Exception { |
|
|
|
|
void getResourceWithHtmlMediaType() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.html"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
|
|
|
|
|
@ -212,11 +210,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -212,11 +210,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("test/foo.html") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceFromAlternatePath() throws Exception { |
|
|
|
|
void getResourceFromAlternatePath() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "baz.css"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
|
|
|
|
|
@ -226,12 +224,12 @@ public class ResourceHttpRequestHandlerTests {
@@ -226,12 +224,12 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.containsHeader("Last-Modified")).isTrue(); |
|
|
|
|
assertThat(this.response.getDateHeader("Last-Modified") / 1000).isEqualTo(resourceLastModified("testalternatepath/baz.css") / 1000); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("h1 { color:red; }"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceFromSubDirectory() throws Exception { |
|
|
|
|
void getResourceFromSubDirectory() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/foo.js"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
|
|
|
|
|
@ -240,7 +238,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -240,7 +238,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getResourceFromSubDirectoryOfAlternatePath() throws Exception { |
|
|
|
|
void getResourceFromSubDirectoryOfAlternatePath() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/baz.js"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
|
|
|
|
|
@ -250,13 +248,13 @@ public class ResourceHttpRequestHandlerTests {
@@ -250,13 +248,13 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
|
|
|
|
|
@Test // SPR-13658
|
|
|
|
|
@SuppressWarnings("deprecation") |
|
|
|
|
public void getResourceWithRegisteredMediaType() throws Exception { |
|
|
|
|
void getResourceWithRegisteredMediaType() throws Exception { |
|
|
|
|
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean(); |
|
|
|
|
factory.addMediaType("bar", new MediaType("foo", "bar")); |
|
|
|
|
factory.afterPropertiesSet(); |
|
|
|
|
ContentNegotiationManager manager = factory.getObject(); |
|
|
|
|
|
|
|
|
|
List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); |
|
|
|
|
List<Resource> paths = List.of(new ClassPathResource("test/", getClass())); |
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setServletContext(new MockServletContext()); |
|
|
|
|
handler.setLocations(paths); |
|
|
|
|
@ -272,13 +270,13 @@ public class ResourceHttpRequestHandlerTests {
@@ -272,13 +270,13 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
|
|
|
|
|
@Test // SPR-14577
|
|
|
|
|
@SuppressWarnings("deprecation") |
|
|
|
|
public void getMediaTypeWithFavorPathExtensionOff() throws Exception { |
|
|
|
|
void getMediaTypeWithFavorPathExtensionOff() throws Exception { |
|
|
|
|
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean(); |
|
|
|
|
factory.setFavorPathExtension(false); |
|
|
|
|
factory.afterPropertiesSet(); |
|
|
|
|
ContentNegotiationManager manager = factory.getObject(); |
|
|
|
|
|
|
|
|
|
List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); |
|
|
|
|
List<Resource> paths = List.of(new ClassPathResource("test/", getClass())); |
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setServletContext(new MockServletContext()); |
|
|
|
|
handler.setLocations(paths); |
|
|
|
|
@ -293,7 +291,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -293,7 +291,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // SPR-14368
|
|
|
|
|
public void getResourceWithMediaTypeResolvedThroughServletContext() throws Exception { |
|
|
|
|
void getResourceWithMediaTypeResolvedThroughServletContext() throws Exception { |
|
|
|
|
MockServletContext servletContext = new MockServletContext() { |
|
|
|
|
@Override |
|
|
|
|
public String getMimeType(String filePath) { |
|
|
|
|
@ -301,7 +299,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -301,7 +299,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass())); |
|
|
|
|
List<Resource> paths = List.of(new ClassPathResource("test/", getClass())); |
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setServletContext(servletContext); |
|
|
|
|
handler.setLocations(paths); |
|
|
|
|
@ -316,8 +314,8 @@ public class ResourceHttpRequestHandlerTests {
@@ -316,8 +314,8 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // gh-27538, gh-27624
|
|
|
|
|
public void filterNonExistingLocations() throws Exception { |
|
|
|
|
List<Resource> inputLocations = Arrays.asList( |
|
|
|
|
void filterNonExistingLocations() throws Exception { |
|
|
|
|
List<Resource> inputLocations = List.of( |
|
|
|
|
new ClassPathResource("test/", getClass()), |
|
|
|
|
new ClassPathResource("testalternatepath/", getClass()), |
|
|
|
|
new ClassPathResource("nosuchpath/", getClass())); |
|
|
|
|
@ -335,7 +333,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -335,7 +333,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void testInvalidPath() throws Exception { |
|
|
|
|
void testInvalidPath() throws Exception { |
|
|
|
|
// Use mock ResourceResolver: i.e. we're only testing upfront validations...
|
|
|
|
|
|
|
|
|
|
Resource resource = mock(Resource.class); |
|
|
|
|
@ -345,8 +343,8 @@ public class ResourceHttpRequestHandlerTests {
@@ -345,8 +343,8 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
given(resolver.resolveResource(any(), any(), any(), any())).willReturn(resource); |
|
|
|
|
|
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); |
|
|
|
|
handler.setResourceResolvers(Collections.singletonList(resolver)); |
|
|
|
|
handler.setLocations(List.of(new ClassPathResource("test/", getClass()))); |
|
|
|
|
handler.setResourceResolvers(List.of(resolver)); |
|
|
|
|
handler.setServletContext(new TestServletContext()); |
|
|
|
|
handler.afterPropertiesSet(); |
|
|
|
|
|
|
|
|
|
@ -355,7 +353,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -355,7 +353,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
testInvalidPath(":/../../testsecret/secret.txt", handler); |
|
|
|
|
|
|
|
|
|
Resource location = new UrlResource(getClass().getResource("./test/")); |
|
|
|
|
this.handler.setLocations(Collections.singletonList(location)); |
|
|
|
|
this.handler.setLocations(List.of(location)); |
|
|
|
|
Resource secretResource = new UrlResource(getClass().getResource("testsecret/secret.txt")); |
|
|
|
|
String secretPath = secretResource.getURL().getPath(); |
|
|
|
|
|
|
|
|
|
@ -377,7 +375,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -377,7 +375,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void resolvePathWithTraversal() throws Exception { |
|
|
|
|
void resolvePathWithTraversal() throws Exception { |
|
|
|
|
for (HttpMethod method : HttpMethod.values()) { |
|
|
|
|
this.request = new MockHttpServletRequest("GET", ""); |
|
|
|
|
this.response = new MockHttpServletResponse(); |
|
|
|
|
@ -389,14 +387,14 @@ public class ResourceHttpRequestHandlerTests {
@@ -389,14 +387,14 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
this.request.setMethod(httpMethod.name()); |
|
|
|
|
|
|
|
|
|
Resource location = new ClassPathResource("test/", getClass()); |
|
|
|
|
this.handler.setLocations(Collections.singletonList(location)); |
|
|
|
|
this.handler.setLocations(List.of(location)); |
|
|
|
|
|
|
|
|
|
testResolvePathWithTraversal(location, "../testsecret/secret.txt"); |
|
|
|
|
testResolvePathWithTraversal(location, "test/../../testsecret/secret.txt"); |
|
|
|
|
testResolvePathWithTraversal(location, ":/../../testsecret/secret.txt"); |
|
|
|
|
|
|
|
|
|
location = new UrlResource(getClass().getResource("./test/")); |
|
|
|
|
this.handler.setLocations(Collections.singletonList(location)); |
|
|
|
|
this.handler.setLocations(List.of(location)); |
|
|
|
|
Resource secretResource = new UrlResource(getClass().getResource("testsecret/secret.txt")); |
|
|
|
|
String secretPath = secretResource.getURL().getPath(); |
|
|
|
|
|
|
|
|
|
@ -422,7 +420,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -422,7 +420,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void ignoreInvalidEscapeSequence() throws Exception { |
|
|
|
|
void ignoreInvalidEscapeSequence() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/%foo%/bar.txt"); |
|
|
|
|
this.response = new MockHttpServletResponse(); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -430,7 +428,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -430,7 +428,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void processPath() { |
|
|
|
|
void processPath() { |
|
|
|
|
// Unchanged
|
|
|
|
|
assertThat(this.handler.processPath("/foo/bar")).isSameAs("/foo/bar"); |
|
|
|
|
assertThat(this.handler.processPath("foo/bar")).isSameAs("foo/bar"); |
|
|
|
|
@ -467,7 +465,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -467,7 +465,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void initAllowedLocations() { |
|
|
|
|
void initAllowedLocations() { |
|
|
|
|
PathResourceResolver resolver = (PathResourceResolver) this.handler.getResourceResolvers().get(0); |
|
|
|
|
Resource[] locations = resolver.getAllowedLocations(); |
|
|
|
|
|
|
|
|
|
@ -475,7 +473,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -475,7 +473,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void initAllowedLocationsWithExplicitConfiguration() throws Exception { |
|
|
|
|
void initAllowedLocationsWithExplicitConfiguration() throws Exception { |
|
|
|
|
ClassPathResource location1 = new ClassPathResource("test/", getClass()); |
|
|
|
|
ClassPathResource location2 = new ClassPathResource("testalternatepath/", getClass()); |
|
|
|
|
|
|
|
|
|
@ -483,16 +481,16 @@ public class ResourceHttpRequestHandlerTests {
@@ -483,16 +481,16 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
pathResolver.setAllowedLocations(location1); |
|
|
|
|
|
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setResourceResolvers(Collections.singletonList(pathResolver)); |
|
|
|
|
handler.setResourceResolvers(List.of(pathResolver)); |
|
|
|
|
handler.setServletContext(new MockServletContext()); |
|
|
|
|
handler.setLocations(Arrays.asList(location1, location2)); |
|
|
|
|
handler.setLocations(List.of(location1, location2)); |
|
|
|
|
handler.afterPropertiesSet(); |
|
|
|
|
|
|
|
|
|
assertThat(pathResolver.getAllowedLocations()).containsExactly(location1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void notModified() throws Exception { |
|
|
|
|
void notModified() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.request.addHeader("If-Modified-Since", resourceLastModified("test/foo.css")); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -500,7 +498,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -500,7 +498,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void modified() throws Exception { |
|
|
|
|
void modified() throws Exception { |
|
|
|
|
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.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -509,34 +507,34 @@ public class ResourceHttpRequestHandlerTests {
@@ -509,34 +507,34 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void directory() throws Exception { |
|
|
|
|
void directory() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "js/"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
assertThat(this.response.getStatus()).isEqualTo(404); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void directoryInJarFile() throws Exception { |
|
|
|
|
void directoryInJarFile() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "underscorejs/"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
assertThat(this.response.getStatus()).isEqualTo(404); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void missingResourcePath() throws Exception { |
|
|
|
|
void missingResourcePath() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, ""); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
assertThat(this.response.getStatus()).isEqualTo(404); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void noPathWithinHandlerMappingAttribute() throws Exception { |
|
|
|
|
void noPathWithinHandlerMappingAttribute() throws Exception { |
|
|
|
|
assertThatIllegalStateException().isThrownBy(() -> |
|
|
|
|
this.handler.handleRequest(this.request, this.response)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void unsupportedHttpMethod() throws Exception { |
|
|
|
|
void unsupportedHttpMethod() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.request.setMethod("POST"); |
|
|
|
|
assertThatExceptionOfType(HttpRequestMethodNotSupportedException.class).isThrownBy(() -> |
|
|
|
|
@ -544,7 +542,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -544,7 +542,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void resourceNotFound() throws Exception { |
|
|
|
|
void resourceNotFound() throws Exception { |
|
|
|
|
for (HttpMethod method : HttpMethod.values()) { |
|
|
|
|
this.request = new MockHttpServletRequest("GET", ""); |
|
|
|
|
this.response = new MockHttpServletResponse(); |
|
|
|
|
@ -560,7 +558,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -560,7 +558,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentByteRange() throws Exception { |
|
|
|
|
void partialContentByteRange() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=0-1"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -571,11 +569,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -571,11 +569,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes 0-1/10"); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("So"); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentByteRangeNoEnd() throws Exception { |
|
|
|
|
void partialContentByteRangeNoEnd() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=9-"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -586,11 +584,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -586,11 +584,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes 9-9/10"); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("."); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentByteRangeLargeEnd() throws Exception { |
|
|
|
|
void partialContentByteRangeLargeEnd() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=9-10000"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -601,11 +599,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -601,11 +599,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes 9-9/10"); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("."); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentSuffixRange() throws Exception { |
|
|
|
|
void partialContentSuffixRange() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=-1"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -616,11 +614,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -616,11 +614,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes 9-9/10"); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("."); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentSuffixRangeLargeSuffix() throws Exception { |
|
|
|
|
void partialContentSuffixRangeLargeSuffix() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=-11"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -631,11 +629,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -631,11 +629,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes 0-9/10"); |
|
|
|
|
assertThat(this.response.getContentAsString()).isEqualTo("Some text."); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentInvalidRangeHeader() throws Exception { |
|
|
|
|
void partialContentInvalidRangeHeader() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes= foo bar"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -643,11 +641,11 @@ public class ResourceHttpRequestHandlerTests {
@@ -643,11 +641,11 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
assertThat(this.response.getStatus()).isEqualTo(416); |
|
|
|
|
assertThat(this.response.getHeader("Content-Range")).isEqualTo("bytes */10"); |
|
|
|
|
assertThat(this.response.getHeader("Accept-Ranges")).isEqualTo("bytes"); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges").size()).isEqualTo(1); |
|
|
|
|
assertThat(this.response.getHeaders("Accept-Ranges")).hasSize(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void partialContentMultipleByteRanges() throws Exception { |
|
|
|
|
void partialContentMultipleByteRanges() throws Exception { |
|
|
|
|
this.request.addHeader("Range", "bytes=0-1, 4-5, 8-9"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -677,13 +675,13 @@ public class ResourceHttpRequestHandlerTests {
@@ -677,13 +675,13 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // gh-25976
|
|
|
|
|
public void partialContentByteRangeWithEncodedResource(GzipSupport.GzippedFiles gzippedFiles) throws Exception { |
|
|
|
|
void partialContentByteRangeWithEncodedResource(GzipSupport.GzippedFiles gzippedFiles) throws Exception { |
|
|
|
|
String path = "js/foo.js"; |
|
|
|
|
gzippedFiles.create(path); |
|
|
|
|
|
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setResourceResolvers(Arrays.asList(new EncodedResourceResolver(), new PathResourceResolver())); |
|
|
|
|
handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); |
|
|
|
|
handler.setResourceResolvers(List.of(new EncodedResourceResolver(), new PathResourceResolver())); |
|
|
|
|
handler.setLocations(List.of(new ClassPathResource("test/", getClass()))); |
|
|
|
|
handler.setServletContext(new MockServletContext()); |
|
|
|
|
handler.afterPropertiesSet(); |
|
|
|
|
|
|
|
|
|
@ -706,7 +704,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -706,7 +704,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // gh-25976
|
|
|
|
|
public void partialContentWithHttpHead() throws Exception { |
|
|
|
|
void partialContentWithHttpHead() throws Exception { |
|
|
|
|
this.request.setMethod("HEAD"); |
|
|
|
|
this.request.addHeader("Range", "bytes=0-1"); |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.txt"); |
|
|
|
|
@ -720,7 +718,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -720,7 +718,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // SPR-14005
|
|
|
|
|
public void doOverwriteExistingCacheControlHeaders() throws Exception { |
|
|
|
|
void doOverwriteExistingCacheControlHeaders() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.response.setHeader("Cache-Control", "no-store"); |
|
|
|
|
|
|
|
|
|
@ -730,7 +728,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -730,7 +728,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void ignoreLastModified() throws Exception { |
|
|
|
|
void ignoreLastModified() throws Exception { |
|
|
|
|
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css"); |
|
|
|
|
this.handler.setUseLastModified(false); |
|
|
|
|
this.handler.handleRequest(this.request, this.response); |
|
|
|
|
@ -742,7 +740,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -742,7 +740,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void servletContextRootValidation() { |
|
|
|
|
void servletContextRootValidation() { |
|
|
|
|
StaticWebApplicationContext context = new StaticWebApplicationContext() { |
|
|
|
|
@Override |
|
|
|
|
public Resource getResource(String location) { |
|
|
|
|
@ -751,7 +749,7 @@ public class ResourceHttpRequestHandlerTests {
@@ -751,7 +749,7 @@ public class ResourceHttpRequestHandlerTests {
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); |
|
|
|
|
handler.setLocationValues(Collections.singletonList("/")); |
|
|
|
|
handler.setLocationValues(List.of("/")); |
|
|
|
|
handler.setApplicationContext(context); |
|
|
|
|
|
|
|
|
|
assertThatIllegalStateException().isThrownBy(handler::afterPropertiesSet) |
|
|
|
|
|