Respect context path in WebMvc.fn & WebFlux.fn
This commit makes several changes in both WebMvc.fn as well as WebFlux.fn. - ServerRequest now exposes a RequestPath through requestPath(), and pathContainer() has been deprecated. - The PathPredicate and PathResourceLookupFunction now respects this RequestPath's pathInApplication() in their path-related functionality. - When nesting, the PathPredicate now appends the matched part of the path to the current context path, instead of removing the matched part (which was done previously). This has the same result: the matched part is gone, but now the full path stays the same. Closes gh-25270
This commit is contained in:
@@ -51,7 +51,6 @@ import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.PathContainer;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -132,13 +131,8 @@ class DefaultServerRequest implements ServerRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String path() {
|
||||
return pathContainer().value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return this.requestPath.pathWithinApplication();
|
||||
public RequestPath requestPath() {
|
||||
return this.requestPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -55,7 +55,7 @@ class PathResourceLookupFunction implements Function<ServerRequest, Optional<Res
|
||||
|
||||
@Override
|
||||
public Optional<Resource> apply(ServerRequest request) {
|
||||
PathContainer pathContainer = request.pathContainer();
|
||||
PathContainer pathContainer = request.requestPath().pathWithinApplication();
|
||||
if (!this.pattern.matches(pathContainer)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@@ -51,6 +50,7 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.PathContainer;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -490,7 +490,7 @@ public abstract class RequestPredicates {
|
||||
|
||||
@Override
|
||||
public boolean test(ServerRequest request) {
|
||||
PathContainer pathContainer = request.pathContainer();
|
||||
PathContainer pathContainer = request.requestPath().pathWithinApplication();
|
||||
PathPattern.PathMatchInfo info = this.pattern.matchAndExtract(pathContainer);
|
||||
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), info != null);
|
||||
if (info != null) {
|
||||
@@ -516,7 +516,7 @@ public abstract class RequestPredicates {
|
||||
|
||||
@Override
|
||||
public Optional<ServerRequest> nest(ServerRequest request) {
|
||||
return Optional.ofNullable(this.pattern.matchStartOfPath(request.pathContainer()))
|
||||
return Optional.ofNullable(this.pattern.matchStartOfPath(request.requestPath().pathWithinApplication()))
|
||||
.map(info -> new SubPathServerRequestWrapper(request, info, this.pattern));
|
||||
}
|
||||
|
||||
@@ -924,17 +924,27 @@ public abstract class RequestPredicates {
|
||||
|
||||
private final ServerRequest request;
|
||||
|
||||
private final PathContainer pathContainer;
|
||||
private RequestPath requestPath;
|
||||
|
||||
private final Map<String, Object> attributes;
|
||||
|
||||
public SubPathServerRequestWrapper(ServerRequest request,
|
||||
PathPattern.PathRemainingMatchInfo info, PathPattern pattern) {
|
||||
this.request = request;
|
||||
this.pathContainer = new SubPathContainer(info.getPathRemaining());
|
||||
this.requestPath = requestPath(request.requestPath(), info);
|
||||
this.attributes = mergeAttributes(request, info.getUriVariables(), pattern);
|
||||
}
|
||||
|
||||
private static RequestPath requestPath(RequestPath original, PathPattern.PathRemainingMatchInfo info) {
|
||||
StringBuilder contextPath = new StringBuilder(original.contextPath().value());
|
||||
contextPath.append(info.getPathMatched().value());
|
||||
int length = contextPath.length();
|
||||
if (length > 0 && contextPath.charAt(length - 1) == '/') {
|
||||
contextPath.setLength(length - 1);
|
||||
}
|
||||
return original.modifyContextPath(contextPath.toString());
|
||||
}
|
||||
|
||||
private static Map<String, Object> mergeAttributes(ServerRequest request,
|
||||
Map<String, String> pathVariables, PathPattern pattern) {
|
||||
Map<String, Object> result = new ConcurrentHashMap<>(request.attributes());
|
||||
@@ -970,13 +980,8 @@ public abstract class RequestPredicates {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String path() {
|
||||
return this.pathContainer.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return this.pathContainer;
|
||||
public RequestPath requestPath() {
|
||||
return this.requestPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1084,46 +1089,6 @@ public abstract class RequestPredicates {
|
||||
return method() + " " + path();
|
||||
}
|
||||
|
||||
private static class SubPathContainer implements PathContainer {
|
||||
|
||||
private static final PathContainer.Separator SEPARATOR = () -> "/";
|
||||
|
||||
|
||||
private final String value;
|
||||
|
||||
private final List<Element> elements;
|
||||
|
||||
public SubPathContainer(PathContainer original) {
|
||||
this.value = prefixWithSlash(original.value());
|
||||
this.elements = prependWithSeparator(original.elements());
|
||||
}
|
||||
|
||||
private static String prefixWithSlash(String path) {
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private static List<Element> prependWithSeparator(List<Element> elements) {
|
||||
List<Element> result = new ArrayList<>(elements);
|
||||
if (result.isEmpty() || !(result.get(0) instanceof Separator)) {
|
||||
result.add(0, SEPARATOR);
|
||||
}
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String value() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Element> elements() {
|
||||
return this.elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,10 +43,12 @@ import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.PathContainer;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.UriBuilder;
|
||||
|
||||
/**
|
||||
@@ -92,14 +94,24 @@ public interface ServerRequest {
|
||||
* Get the request path.
|
||||
*/
|
||||
default String path() {
|
||||
return uri().getRawPath();
|
||||
return requestPath().pathWithinApplication().value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request path as a {@code PathContainer}.
|
||||
* @deprecated as of 5.3, in favor on {@link #requestPath()}
|
||||
*/
|
||||
@Deprecated
|
||||
default PathContainer pathContainer() {
|
||||
return PathContainer.parsePath(path());
|
||||
return requestPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request path as a {@code PathContainer}.
|
||||
* @since 5.3
|
||||
*/
|
||||
default RequestPath requestPath() {
|
||||
return ServletRequestPathUtils.getParsedRequestPath(servletRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user