Use PathContainer in web.reactive.function.server
This commit uses the newly introduced `PathContainer` and `RequestPath` support in the functional web framework. It exposes the path container as property in `ServerRequest`, and uses that in the path-based `RequestPredicates`.
This commit is contained in:
@@ -38,6 +38,7 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.server.reactive.PathContainer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -92,6 +93,11 @@ class DefaultServerRequest implements ServerRequest {
|
||||
return request().getURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return request().getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers headers() {
|
||||
return this.headers;
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.reactive.function.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -37,6 +38,7 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.PathContainer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -339,9 +341,8 @@ public abstract class RequestPredicates {
|
||||
|
||||
@Override
|
||||
public boolean test(ServerRequest request) {
|
||||
String path = request.path();
|
||||
boolean match = this.pattern.matches(path);
|
||||
traceMatch("Pattern", this.pattern.getPatternString(), path, match);
|
||||
boolean match = this.pattern.matches(request.pathContainer());
|
||||
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), match);
|
||||
if (match) {
|
||||
mergeTemplateVariables(request, this.pattern.matchAndExtract(request.path()).getUriVariables());
|
||||
return true;
|
||||
@@ -353,14 +354,10 @@ public abstract class RequestPredicates {
|
||||
|
||||
@Override
|
||||
public Optional<ServerRequest> nest(ServerRequest request) {
|
||||
return Optional.ofNullable(this.pattern.getPathRemaining(request.path()))
|
||||
return Optional.ofNullable(this.pattern.getPathRemaining(request.pathContainer()))
|
||||
.map(info -> {
|
||||
mergeTemplateVariables(request, info.getUriVariables());
|
||||
String path = info.getPathRemaining();
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return new SubPathServerRequestWrapper(request, path);
|
||||
return new SubPathServerRequestWrapper(request, info);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -464,12 +461,12 @@ public abstract class RequestPredicates {
|
||||
|
||||
private final ServerRequest request;
|
||||
|
||||
private final String subPath;
|
||||
private final PathContainer subPathContainer;
|
||||
|
||||
|
||||
public SubPathServerRequestWrapper(ServerRequest request, String subPath) {
|
||||
public SubPathServerRequestWrapper(ServerRequest request, PathPattern.PathRemainingMatchInfo info) {
|
||||
this.request = request;
|
||||
this.subPath = subPath;
|
||||
this.subPathContainer = new SubPathContainer(info.getPathRemaining());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -484,7 +481,12 @@ public abstract class RequestPredicates {
|
||||
|
||||
@Override
|
||||
public String path() {
|
||||
return this.subPath;
|
||||
return this.subPathContainer.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return this.subPathContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -561,6 +563,47 @@ public abstract class RequestPredicates {
|
||||
public String toString() {
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.web.reactive.function.server;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Principal;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -36,6 +37,7 @@ import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.codec.json.Jackson2CodecSupport;
|
||||
import org.springframework.http.server.reactive.PathContainer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -72,6 +74,13 @@ public interface ServerRequest {
|
||||
return uri().getRawPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the request path as {@code PathContainer}.
|
||||
*/
|
||||
default PathContainer pathContainer() {
|
||||
return PathContainer.parse(path(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the headers of this request.
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.PathContainer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -87,6 +88,11 @@ public class ServerRequestWrapper implements ServerRequest {
|
||||
return this.delegate.path();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return this.delegate.pathContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers headers() {
|
||||
return this.delegate.headers();
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.web.reactive.function.server;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -38,6 +39,8 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.PathContainer;
|
||||
import org.springframework.http.server.reactive.RequestPath;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -48,6 +51,7 @@ import org.springframework.web.server.WebSession;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ServerRequest}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.0
|
||||
*/
|
||||
@@ -57,6 +61,8 @@ public class MockServerRequest implements ServerRequest {
|
||||
|
||||
private final URI uri;
|
||||
|
||||
private final RequestPath pathContainer;
|
||||
|
||||
private final MockHeaders headers;
|
||||
|
||||
private final MultiValueMap<String, HttpCookie> cookies;
|
||||
@@ -76,13 +82,15 @@ public class MockServerRequest implements ServerRequest {
|
||||
@Nullable
|
||||
private Principal principal;
|
||||
|
||||
private MockServerRequest(HttpMethod method, URI uri,
|
||||
MockHeaders headers, MultiValueMap<String, HttpCookie> cookies, @Nullable Object body,
|
||||
|
||||
private MockServerRequest(HttpMethod method, URI uri, String contextPath, MockHeaders headers,
|
||||
MultiValueMap<String, HttpCookie> cookies, @Nullable Object body,
|
||||
Map<String, Object> attributes, MultiValueMap<String, String> queryParams,
|
||||
Map<String, String> pathVariables, @Nullable WebSession session, @Nullable Principal principal) {
|
||||
|
||||
this.method = method;
|
||||
this.uri = uri;
|
||||
this.pathContainer = RequestPath.create(uri, contextPath, StandardCharsets.UTF_8);
|
||||
this.headers = headers;
|
||||
this.cookies = cookies;
|
||||
this.body = body;
|
||||
@@ -104,6 +112,11 @@ public class MockServerRequest implements ServerRequest {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathContainer pathContainer() {
|
||||
return this.pathContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers headers() {
|
||||
return this.headers;
|
||||
@@ -116,7 +129,7 @@ public class MockServerRequest implements ServerRequest {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor){
|
||||
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor) {
|
||||
Assert.state(this.body != null, "No body");
|
||||
return (S) this.body;
|
||||
}
|
||||
@@ -186,6 +199,8 @@ public class MockServerRequest implements ServerRequest {
|
||||
|
||||
Builder uri(URI uri);
|
||||
|
||||
Builder contextPath(String contextPath);
|
||||
|
||||
Builder header(String key, String value);
|
||||
|
||||
Builder headers(HttpHeaders headers);
|
||||
@@ -222,6 +237,8 @@ public class MockServerRequest implements ServerRequest {
|
||||
|
||||
private URI uri = URI.create("http://localhost");
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private MockHeaders headers = new MockHeaders(new HttpHeaders());
|
||||
|
||||
private MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
|
||||
@@ -256,18 +273,11 @@ public class MockServerRequest implements ServerRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder header(String key, String value) {
|
||||
Assert.notNull(key, "'key' must not be null");
|
||||
Assert.notNull(value, "'value' must not be null");
|
||||
this.headers.header(key, value);
|
||||
public Builder contextPath(String contextPath) {
|
||||
Assert.notNull(contextPath, "'contextPath' must not be null");
|
||||
this.contextPath = contextPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder headers(HttpHeaders headers) {
|
||||
Assert.notNull(headers, "'headers' must not be null");
|
||||
this.headers = new MockHeaders(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -283,6 +293,21 @@ public class MockServerRequest implements ServerRequest {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder header(String key, String value) {
|
||||
Assert.notNull(key, "'key' must not be null");
|
||||
Assert.notNull(value, "'value' must not be null");
|
||||
this.headers.header(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder headers(HttpHeaders headers) {
|
||||
Assert.notNull(headers, "'headers' must not be null");
|
||||
this.headers = new MockHeaders(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder attribute(String name, Object value) {
|
||||
Assert.notNull(name, "'name' must not be null");
|
||||
@@ -345,16 +370,16 @@ public class MockServerRequest implements ServerRequest {
|
||||
@Override
|
||||
public MockServerRequest body(Object body) {
|
||||
this.body = body;
|
||||
return new MockServerRequest(this.method, this.uri, this.headers, this.cookies,
|
||||
this.body, this.attributes, this.queryParams, this.pathVariables, this.session,
|
||||
this.principal);
|
||||
return new MockServerRequest(this.method, this.uri, this.contextPath, this.headers,
|
||||
this.cookies, this.body, this.attributes, this.queryParams, this.pathVariables,
|
||||
this.session, this.principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerRequest build() {
|
||||
return new MockServerRequest(this.method, this.uri, this.headers, this.cookies, null,
|
||||
this.attributes, this.queryParams, this.pathVariables, this.session,
|
||||
this.principal);
|
||||
return new MockServerRequest(this.method, this.uri, this.contextPath, this.headers,
|
||||
this.cookies, null, this.attributes, this.queryParams, this.pathVariables,
|
||||
this.session, this.principal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user