Resolve static resources without wildcard pattern
Prior to this commit, the reactive `ResourceWebHandler` would only look at the path within the current mapping when resolving static resources to be served. This means that when registering a handler at `"/resources/**"` with a `"classpath:/static/"` location, the handler would process a `"GET /resources/file.txt"` as the `"/static/file.txt"` classpath location. When a developer registers a fixed pattern like `"/resources/file.txt"` with the same location, the path within the handler mapping is empty as there is no dynamic part in the given pattern. While the typical use case for this feature is to register multiple resources at once with a pattern, we should support a single registration like this. This commit ensures that if the matching `PathPattern` for the current request does not have a pattern syntax (i.e. no regexp, no wildcard), we can use it to match the resource directly. Otherwise, we can use the path within the handler mapping to resolve the resource as before. Closes gh-29739
This commit is contained in:
parent
3f148c2aaa
commit
d37ef61b30
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -57,6 +57,7 @@ import org.springframework.web.server.MethodNotAllowedException;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.WebHandler;
|
import org.springframework.web.server.WebHandler;
|
||||||
|
import org.springframework.web.util.pattern.PathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code HttpRequestHandler} that serves static resources in an optimized way
|
* {@code HttpRequestHandler} that serves static resources in an optimized way
|
||||||
|
|
@ -456,10 +457,8 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Mono<Resource> getResource(ServerWebExchange exchange) {
|
protected Mono<Resource> getResource(ServerWebExchange exchange) {
|
||||||
String name = HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE;
|
String rawPath = getResourcePath(exchange);
|
||||||
PathContainer pathWithinHandler = exchange.getRequiredAttribute(name);
|
String path = processPath(rawPath);
|
||||||
|
|
||||||
String path = processPath(pathWithinHandler.value());
|
|
||||||
if (!StringUtils.hasText(path) || isInvalidPath(path)) {
|
if (!StringUtils.hasText(path) || isInvalidPath(path)) {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
|
@ -474,6 +473,15 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
|
||||||
.flatMap(resource -> this.transformerChain.transform(exchange, resource));
|
.flatMap(resource -> this.transformerChain.transform(exchange, resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getResourcePath(ServerWebExchange exchange) {
|
||||||
|
PathPattern pattern = exchange.getRequiredAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||||
|
if (!pattern.hasPatternSyntax()) {
|
||||||
|
return pattern.getPatternString();
|
||||||
|
}
|
||||||
|
PathContainer pathWithinHandler = exchange.getRequiredAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||||
|
return pathWithinHandler.value();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the given resource path.
|
* Process the given resource path.
|
||||||
* <p>The default implementation replaces:
|
* <p>The default implementation replaces:
|
||||||
|
|
@ -484,7 +492,6 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
|
||||||
* with a single "/" or "". For example {@code " / // foo/bar"}
|
* with a single "/" or "". For example {@code " / // foo/bar"}
|
||||||
* becomes {@code "/foo/bar"}.
|
* becomes {@code "/foo/bar"}.
|
||||||
* </ul>
|
* </ul>
|
||||||
* @since 3.2.12
|
|
||||||
*/
|
*/
|
||||||
protected String processPath(String path) {
|
protected String processPath(String path) {
|
||||||
path = StringUtils.replace(path, "\\", "/");
|
path = StringUtils.replace(path, "\\", "/");
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ import org.springframework.web.reactive.resource.VersionResourceResolver;
|
||||||
import org.springframework.web.reactive.resource.WebJarsResourceResolver;
|
import org.springframework.web.reactive.resource.WebJarsResourceResolver;
|
||||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||||
|
import org.springframework.web.util.pattern.PathPatternParser;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -82,6 +83,8 @@ class ResourceHandlerRegistryTests {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
exchange.getAttributes().put(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
|
exchange.getAttributes().put(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
|
||||||
PathContainer.parsePath("/testStylesheet.css"));
|
PathContainer.parsePath("/testStylesheet.css"));
|
||||||
|
exchange.getAttributes().put(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE,
|
||||||
|
new PathPatternParser().parse("/**"));
|
||||||
|
|
||||||
ResourceWebHandler handler = getHandler("/resources/**");
|
ResourceWebHandler handler = getHandler("/resources/**");
|
||||||
handler.handle(exchange).block(Duration.ofSeconds(5));
|
handler.handle(exchange).block(Duration.ofSeconds(5));
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRe
|
||||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
import org.springframework.web.util.pattern.PathPatternParser;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -72,6 +73,7 @@ import static org.mockito.Mockito.mock;
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
class ResourceWebHandlerTests {
|
class ResourceWebHandlerTests {
|
||||||
|
|
||||||
|
|
@ -102,6 +104,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResource() throws Exception {
|
void getResource() throws Exception {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -119,6 +122,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceHttpHeader() throws Exception {
|
void getResourceHttpHeader() throws Exception {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.head(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.head(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat((Object) exchange.getResponse().getStatusCode()).isNull();
|
assertThat((Object) exchange.getResponse().getStatusCode()).isNull();
|
||||||
|
|
@ -139,6 +143,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceHttpOptions() {
|
void getResourceHttpOptions() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.options(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.options(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isNull();
|
assertThat(exchange.getResponse().getStatusCode()).isNull();
|
||||||
|
|
@ -149,6 +154,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceNoCache() throws Exception {
|
void getResourceNoCache() throws Exception {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.setCacheControl(CacheControl.noStore());
|
this.handler.setCacheControl(CacheControl.noStore());
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
|
|
@ -169,6 +175,7 @@ class ResourceWebHandlerTests {
|
||||||
|
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "versionString/foo.css");
|
setPathWithinHandlerMapping(exchange, "versionString/foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getHeaders().getETag()).isEqualTo("W/\"versionString\"");
|
assertThat(exchange.getResponse().getHeaders().getETag()).isEqualTo("W/\"versionString\"");
|
||||||
|
|
@ -180,6 +187,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceWithHtmlMediaType() throws Exception {
|
void getResourceWithHtmlMediaType() throws Exception {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.html");
|
setPathWithinHandlerMapping(exchange, "foo.html");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -195,6 +203,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceFromAlternatePath() throws Exception {
|
void getResourceFromAlternatePath() throws Exception {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "baz.css");
|
setPathWithinHandlerMapping(exchange, "baz.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -212,6 +221,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceFromSubDirectory() {
|
void getResourceFromSubDirectory() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "js/foo.js");
|
setPathWithinHandlerMapping(exchange, "js/foo.js");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.parseMediaType("application/javascript"));
|
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.parseMediaType("application/javascript"));
|
||||||
|
|
@ -222,6 +232,7 @@ class ResourceWebHandlerTests {
|
||||||
void getResourceFromSubDirectoryOfAlternatePath() {
|
void getResourceFromSubDirectoryOfAlternatePath() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "js/baz.js");
|
setPathWithinHandlerMapping(exchange, "js/baz.js");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -229,6 +240,18 @@ class ResourceWebHandlerTests {
|
||||||
assertResponseBody(exchange, "function foo() { console.log(\"hello world\"); }");
|
assertResponseBody(exchange, "function foo() { console.log(\"hello world\"); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getResourceWithFullPathAsPattern() {
|
||||||
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/foo.css"));
|
||||||
|
setPathWithinHandlerMapping(exchange, "");
|
||||||
|
setBestMachingPattern(exchange, "/foo.css");
|
||||||
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers.getContentType()).isEqualTo(MediaType.parseMediaType("text/css"));
|
||||||
|
assertThat(headers.getContentLength()).isEqualTo(17);
|
||||||
|
assertResponseBody(exchange, "h1 { color:red; }");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getResourceWithRegisteredMediaType() throws Exception {
|
void getResourceWithRegisteredMediaType() throws Exception {
|
||||||
MediaType mediaType = new MediaType("foo", "bar");
|
MediaType mediaType = new MediaType("foo", "bar");
|
||||||
|
|
@ -240,6 +263,7 @@ class ResourceWebHandlerTests {
|
||||||
|
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.bar");
|
setPathWithinHandlerMapping(exchange, "foo.bar");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
handler.handle(exchange).block(TIMEOUT);
|
handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -258,6 +282,7 @@ class ResourceWebHandlerTests {
|
||||||
|
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, UriUtils.encodePath("test/foo with spaces.css", UTF_8));
|
setPathWithinHandlerMapping(exchange, UriUtils.encodePath("test/foo with spaces.css", UTF_8));
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
handler.handle(exchange).block(TIMEOUT);
|
handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||||
|
|
@ -294,6 +319,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("")
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("")
|
||||||
.header("Accept", "application/json,text/plain,*/*"));
|
.header("Accept", "application/json,text/plain,*/*"));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.html");
|
setPathWithinHandlerMapping(exchange, "foo.html");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
handler.handle(exchange).block(TIMEOUT);
|
handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.TEXT_HTML);
|
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.TEXT_HTML);
|
||||||
|
|
@ -337,7 +363,7 @@ class ResourceWebHandlerTests {
|
||||||
private void testInvalidPath(String requestPath, ResourceWebHandler handler) {
|
private void testInvalidPath(String requestPath, ResourceWebHandler handler) {
|
||||||
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, requestPath);
|
setPathWithinHandlerMapping(exchange, requestPath);
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
StepVerifier.create(handler.handle(exchange))
|
StepVerifier.create(handler.handle(exchange))
|
||||||
.expectErrorSatisfies(err -> {
|
.expectErrorSatisfies(err -> {
|
||||||
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
||||||
|
|
@ -379,6 +405,7 @@ class ResourceWebHandlerTests {
|
||||||
|
|
||||||
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.method(httpMethod, ""));
|
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.method(httpMethod, ""));
|
||||||
setPathWithinHandlerMapping(exchange, requestPath);
|
setPathWithinHandlerMapping(exchange, requestPath);
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
StepVerifier.create(this.handler.handle(exchange))
|
StepVerifier.create(this.handler.handle(exchange))
|
||||||
.expectErrorSatisfies(err -> {
|
.expectErrorSatisfies(err -> {
|
||||||
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
||||||
|
|
@ -449,6 +476,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest.get("").ifModifiedSince(resourceLastModified("test/foo.css")));
|
MockServerHttpRequest.get("").ifModifiedSince(resourceLastModified("test/foo.css")));
|
||||||
|
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.NOT_MODIFIED);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.NOT_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
@ -459,6 +487,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").ifModifiedSince(timestamp).build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").ifModifiedSince(timestamp).build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat((Object) exchange.getResponse().getStatusCode()).isNull();
|
assertThat((Object) exchange.getResponse().getStatusCode()).isNull();
|
||||||
|
|
@ -469,6 +498,7 @@ class ResourceWebHandlerTests {
|
||||||
void directory() {
|
void directory() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "js/");
|
setPathWithinHandlerMapping(exchange, "js/");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
StepVerifier.create(this.handler.handle(exchange))
|
StepVerifier.create(this.handler.handle(exchange))
|
||||||
.expectErrorSatisfies(err -> {
|
.expectErrorSatisfies(err -> {
|
||||||
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
||||||
|
|
@ -480,6 +510,7 @@ class ResourceWebHandlerTests {
|
||||||
void directoryInJarFile() {
|
void directoryInJarFile() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "underscorejs/");
|
setPathWithinHandlerMapping(exchange, "underscorejs/");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
StepVerifier.create(this.handler.handle(exchange))
|
StepVerifier.create(this.handler.handle(exchange))
|
||||||
.expectErrorSatisfies(err -> {
|
.expectErrorSatisfies(err -> {
|
||||||
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
||||||
|
|
@ -491,6 +522,7 @@ class ResourceWebHandlerTests {
|
||||||
void missingResourcePath() {
|
void missingResourcePath() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "");
|
setPathWithinHandlerMapping(exchange, "");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
StepVerifier.create(this.handler.handle(exchange))
|
StepVerifier.create(this.handler.handle(exchange))
|
||||||
.expectErrorSatisfies(err -> {
|
.expectErrorSatisfies(err -> {
|
||||||
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
assertThat(err).isInstanceOf(ResponseStatusException.class);
|
||||||
|
|
@ -509,6 +541,7 @@ class ResourceWebHandlerTests {
|
||||||
void unsupportedHttpMethod() {
|
void unsupportedHttpMethod() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
assertThatExceptionOfType(MethodNotAllowedException.class).isThrownBy(() ->
|
assertThatExceptionOfType(MethodNotAllowedException.class).isThrownBy(() ->
|
||||||
this.handler.handle(exchange).block(TIMEOUT));
|
this.handler.handle(exchange).block(TIMEOUT));
|
||||||
}
|
}
|
||||||
|
|
@ -519,6 +552,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.method(method, "").build();
|
MockServerHttpRequest request = MockServerHttpRequest.method(method, "").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "not-there.css");
|
setPathWithinHandlerMapping(exchange, "not-there.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
Mono<Void> mono = this.handler.handle(exchange);
|
Mono<Void> mono = this.handler.handle(exchange);
|
||||||
|
|
||||||
StepVerifier.create(mono)
|
StepVerifier.create(mono)
|
||||||
|
|
@ -538,6 +572,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("Range", "bytes=0-1").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("Range", "bytes=0-1").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -554,6 +589,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=9-").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=9-").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -570,6 +606,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=9-10000").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=9-10000").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -586,6 +623,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=-1").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=-1").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -602,6 +640,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=-11").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=-11").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -618,6 +657,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=foo bar").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("range", "bytes=foo bar").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
|
|
||||||
StepVerifier.create(this.handler.handle(exchange))
|
StepVerifier.create(this.handler.handle(exchange))
|
||||||
.expectNextCount(0)
|
.expectNextCount(0)
|
||||||
|
|
@ -633,6 +673,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerHttpRequest request = MockServerHttpRequest.get("").header("Range", "bytes=0-1, 4-5, 8-9").build();
|
MockServerHttpRequest request = MockServerHttpRequest.get("").header("Range", "bytes=0-1, 4-5, 8-9").build();
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||||
setPathWithinHandlerMapping(exchange, "foo.txt");
|
setPathWithinHandlerMapping(exchange, "foo.txt");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT);
|
||||||
|
|
@ -677,6 +718,7 @@ class ResourceWebHandlerTests {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
exchange.getResponse().getHeaders().setCacheControl(CacheControl.noStore().getHeaderValue());
|
exchange.getResponse().getHeaders().setCacheControl(CacheControl.noStore().getHeaderValue());
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
assertThat(exchange.getResponse().getHeaders().getCacheControl()).isEqualTo("max-age=3600");
|
assertThat(exchange.getResponse().getHeaders().getCacheControl()).isEqualTo("max-age=3600");
|
||||||
|
|
@ -686,6 +728,7 @@ class ResourceWebHandlerTests {
|
||||||
void ignoreLastModified() {
|
void ignoreLastModified() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(""));
|
||||||
setPathWithinHandlerMapping(exchange, "foo.css");
|
setPathWithinHandlerMapping(exchange, "foo.css");
|
||||||
|
setBestMachingPattern(exchange, "/**");
|
||||||
this.handler.setUseLastModified(false);
|
this.handler.setUseLastModified(false);
|
||||||
this.handler.handle(exchange).block(TIMEOUT);
|
this.handler.handle(exchange).block(TIMEOUT);
|
||||||
|
|
||||||
|
|
@ -702,6 +745,11 @@ class ResourceWebHandlerTests {
|
||||||
PathContainer.parsePath(path));
|
PathContainer.parsePath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setBestMachingPattern(ServerWebExchange exchange, String pattern) {
|
||||||
|
exchange.getAttributes().put(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE,
|
||||||
|
new PathPatternParser().parse(pattern));
|
||||||
|
}
|
||||||
|
|
||||||
private long resourceLastModified(String resourceName) throws IOException {
|
private long resourceLastModified(String resourceName) throws IOException {
|
||||||
return new ClassPathResource(resourceName, getClass()).getFile().lastModified();
|
return new ClassPathResource(resourceName, getClass()).getFile().lastModified();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue