Skip to content

Commit 95196e1

Browse files
committed
Use undecoded pathWithinApplication in WebFlux
Introduce pathWithinApplication() in ServerHttpRequest and use it for request mapping purposes instead of LookupPath. In turn this means that for request mapping purposes: 1) the path is not decoded 2) suffix pattern matching is not supported Issue: SPR-15640
1 parent ff2af66 commit 95196e1

File tree

19 files changed

+108
-410
lines changed

19 files changed

+108
-410
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/ContextPathCompositeHandler.java

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
import java.util.LinkedHashMap;
55
import java.util.Map;
66

7+
import reactor.core.publisher.Mono;
8+
79
import org.springframework.http.HttpStatus;
810
import org.springframework.util.Assert;
9-
import org.springframework.util.StringUtils;
10-
11-
import reactor.core.publisher.Mono;
1211

1312
/**
1413
* {@code HttpHandler} delegating requests to one of several {@code HttpHandler}'s
@@ -49,7 +48,8 @@ private static void assertValidContextPath(String contextPath) {
4948

5049
@Override
5150
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
52-
String path = getPathWithinApplication(request);
51+
// Remove underlying context path first (e.g. Servlet container)
52+
String path = request.getPathWithinApplication();
5353
return this.handlerMap.entrySet().stream()
5454
.filter(entry -> path.startsWith(entry.getKey()))
5555
.findFirst()
@@ -65,18 +65,4 @@ public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response)
6565
});
6666
}
6767

68-
/**
69-
* Get the path within the "native" context path of the underlying server,
70-
* for example when running on a Servlet container.
71-
*/
72-
private String getPathWithinApplication(ServerHttpRequest request) {
73-
String path = request.getURI().getRawPath();
74-
String contextPath = request.getContextPath();
75-
if (!StringUtils.hasText(contextPath)) {
76-
return path;
77-
}
78-
int length = contextPath.length();
79-
return (path.length() > length ? path.substring(length) : "");
80-
}
81-
8268
}

spring-web/src/main/java/org/springframework/http/server/reactive/ServerHttpRequest.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.http.ReactiveHttpInputMessage;
2525
import org.springframework.lang.Nullable;
2626
import org.springframework.util.MultiValueMap;
27+
import org.springframework.util.StringUtils;
2728

2829
/**
2930
* Represents a reactive server-side HTTP request
@@ -35,16 +36,36 @@
3536
public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage {
3637

3738
/**
38-
* Returns the portion of the URL path that represents the context path for the
39-
* current {@link HttpHandler}. The context path is always at the beginning of
40-
* the request path. It starts with "/" but but does not end with "/".
41-
* <p>This method may return an empty string if no context path is configured.
39+
* Returns the portion of the URL path that represents the application.
40+
* The context path is always at the beginning of the path and starts but
41+
* does not end with "/". It is shared for URLs of the same application.
42+
* <p>The context path may come from the underlying runtime API such as
43+
* when deploying as a WAR to a Servlet container or it may also be assigned
44+
* through the use of {@link ContextPathCompositeHandler} or both.
45+
* <p>The context path is not decoded.
4246
* @return the context path (not decoded) or an empty string
4347
*/
4448
default String getContextPath() {
4549
return "";
4650
}
4751

52+
/**
53+
* Returns the portion of the URL path after the {@link #getContextPath()
54+
* contextPath}. The returned path is not decoded.
55+
* @return the path under the contextPath
56+
*/
57+
default String getPathWithinApplication() {
58+
String path = getURI().getRawPath();
59+
String contextPath = getContextPath();
60+
if (StringUtils.hasText(contextPath)) {
61+
int length = contextPath.length();
62+
return (path.length() > length ? path.substring(length) : "");
63+
}
64+
else {
65+
return path;
66+
}
67+
}
68+
4869
/**
4970
* Return a read-only map with parsed and decoded query parameter values.
5071
*/

spring-web/src/main/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSource.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.springframework.util.PathMatcher;
2626
import org.springframework.web.cors.CorsConfiguration;
2727
import org.springframework.web.server.ServerWebExchange;
28-
import org.springframework.web.server.support.LookupPath;
2928
import org.springframework.web.util.pattern.ParsingPathMatcher;
3029

3130
/**
@@ -81,7 +80,7 @@ public void registerCorsConfiguration(String path, CorsConfiguration config) {
8180

8281
@Override
8382
public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
84-
String lookupPath = LookupPath.getCurrent(exchange).getPath();
83+
String lookupPath = exchange.getRequest().getPathWithinApplication();
8584
for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
8685
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
8786
return entry.getValue();

spring-web/src/main/java/org/springframework/web/server/support/HttpRequestPathHelper.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*/
3737
public class HttpRequestPathHelper {
3838

39-
private boolean urlDecode = true;
39+
private boolean urlDecode = false;
4040

4141

4242
// TODO: sanitize path, default/request encoding?, remove path params?
@@ -58,26 +58,6 @@ public boolean shouldUrlDecode() {
5858
}
5959

6060

61-
public LookupPath getLookupPathForRequest(ServerWebExchange exchange) {
62-
String path = getPathWithinApplication(exchange.getRequest());
63-
path = (shouldUrlDecode() ? decode(exchange, path) : path);
64-
int begin = path.lastIndexOf('/') + 1;
65-
int end = path.length();
66-
int paramIndex = path.indexOf(';', begin);
67-
int extIndex = path.lastIndexOf('.', paramIndex != -1 ? paramIndex : end);
68-
return new LookupPath(path, extIndex, paramIndex);
69-
}
70-
71-
private String getPathWithinApplication(ServerHttpRequest request) {
72-
String contextPath = request.getContextPath();
73-
String path = request.getURI().getRawPath();
74-
if (!StringUtils.hasText(contextPath)) {
75-
return path;
76-
}
77-
int contextLength = contextPath.length();
78-
return (path.length() > contextLength ? path.substring(contextLength) : "");
79-
}
80-
8161
private String decode(ServerWebExchange exchange, String path) {
8262
// TODO: look up request encoding?
8363
try {

spring-web/src/main/java/org/springframework/web/server/support/LookupPath.java

Lines changed: 0 additions & 109 deletions
This file was deleted.

spring-web/src/test/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSourceTests.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
2222
import org.springframework.web.cors.CorsConfiguration;
2323
import org.springframework.web.server.ServerWebExchange;
24-
import org.springframework.web.server.support.HttpRequestPathHelper;
25-
import org.springframework.web.server.support.LookupPath;
2624

2725
import static org.junit.Assert.assertEquals;
2826
import static org.junit.Assert.assertNull;
@@ -41,7 +39,6 @@ public class UrlBasedCorsConfigurationSourceTests {
4139
@Test
4240
public void empty() {
4341
ServerWebExchange exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
44-
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
4542
assertNull(this.configSource.getCorsConfiguration(exchange));
4643
}
4744

@@ -51,11 +48,9 @@ public void registerAndMatch() {
5148
this.configSource.registerCorsConfiguration("/bar/**", config);
5249

5350
ServerWebExchange exchange = MockServerHttpRequest.get("/foo/test.html").toExchange();
54-
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
5551
assertNull(this.configSource.getCorsConfiguration(exchange));
5652

5753
exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
58-
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
5954
assertEquals(config, this.configSource.getCorsConfiguration(exchange));
6055
}
6156

spring-web/src/test/java/org/springframework/web/server/support/LookupPathTests.java

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)