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
This commit is contained in:
parent
ff2af660cf
commit
95196e1aee
|
|
@ -4,11 +4,10 @@ package org.springframework.http.server.reactive;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code HttpHandler} delegating requests to one of several {@code HttpHandler}'s
|
* {@code HttpHandler} delegating requests to one of several {@code HttpHandler}'s
|
||||||
|
|
@ -49,7 +48,8 @@ public class ContextPathCompositeHandler implements HttpHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||||
String path = getPathWithinApplication(request);
|
// Remove underlying context path first (e.g. Servlet container)
|
||||||
|
String path = request.getPathWithinApplication();
|
||||||
return this.handlerMap.entrySet().stream()
|
return this.handlerMap.entrySet().stream()
|
||||||
.filter(entry -> path.startsWith(entry.getKey()))
|
.filter(entry -> path.startsWith(entry.getKey()))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
|
|
@ -65,18 +65,4 @@ public class ContextPathCompositeHandler implements HttpHandler {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the path within the "native" context path of the underlying server,
|
|
||||||
* for example when running on a Servlet container.
|
|
||||||
*/
|
|
||||||
private String getPathWithinApplication(ServerHttpRequest request) {
|
|
||||||
String path = request.getURI().getRawPath();
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
if (!StringUtils.hasText(contextPath)) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
int length = contextPath.length();
|
|
||||||
return (path.length() > length ? path.substring(length) : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.http.ReactiveHttpInputMessage;
|
import org.springframework.http.ReactiveHttpInputMessage;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a reactive server-side HTTP request
|
* Represents a reactive server-side HTTP request
|
||||||
|
|
@ -35,16 +36,36 @@ import org.springframework.util.MultiValueMap;
|
||||||
public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage {
|
public interface ServerHttpRequest extends HttpRequest, ReactiveHttpInputMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the portion of the URL path that represents the context path for the
|
* Returns the portion of the URL path that represents the application.
|
||||||
* current {@link HttpHandler}. The context path is always at the beginning of
|
* The context path is always at the beginning of the path and starts but
|
||||||
* the request path. It starts with "/" but but does not end with "/".
|
* does not end with "/". It is shared for URLs of the same application.
|
||||||
* <p>This method may return an empty string if no context path is configured.
|
* <p>The context path may come from the underlying runtime API such as
|
||||||
|
* when deploying as a WAR to a Servlet container or it may also be assigned
|
||||||
|
* through the use of {@link ContextPathCompositeHandler} or both.
|
||||||
|
* <p>The context path is not decoded.
|
||||||
* @return the context path (not decoded) or an empty string
|
* @return the context path (not decoded) or an empty string
|
||||||
*/
|
*/
|
||||||
default String getContextPath() {
|
default String getContextPath() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the portion of the URL path after the {@link #getContextPath()
|
||||||
|
* contextPath}. The returned path is not decoded.
|
||||||
|
* @return the path under the contextPath
|
||||||
|
*/
|
||||||
|
default String getPathWithinApplication() {
|
||||||
|
String path = getURI().getRawPath();
|
||||||
|
String contextPath = getContextPath();
|
||||||
|
if (StringUtils.hasText(contextPath)) {
|
||||||
|
int length = contextPath.length();
|
||||||
|
return (path.length() > length ? path.substring(length) : "");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a read-only map with parsed and decoded query parameter values.
|
* Return a read-only map with parsed and decoded query parameter values.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.PathMatcher;
|
import org.springframework.util.PathMatcher;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -81,7 +80,7 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
|
public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
|
||||||
String lookupPath = LookupPath.getCurrent(exchange).getPath();
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
|
for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
|
||||||
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
|
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import org.springframework.web.util.UriUtils;
|
||||||
*/
|
*/
|
||||||
public class HttpRequestPathHelper {
|
public class HttpRequestPathHelper {
|
||||||
|
|
||||||
private boolean urlDecode = true;
|
private boolean urlDecode = false;
|
||||||
|
|
||||||
|
|
||||||
// TODO: sanitize path, default/request encoding?, remove path params?
|
// TODO: sanitize path, default/request encoding?, remove path params?
|
||||||
|
|
@ -58,26 +58,6 @@ public class HttpRequestPathHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LookupPath getLookupPathForRequest(ServerWebExchange exchange) {
|
|
||||||
String path = getPathWithinApplication(exchange.getRequest());
|
|
||||||
path = (shouldUrlDecode() ? decode(exchange, path) : path);
|
|
||||||
int begin = path.lastIndexOf('/') + 1;
|
|
||||||
int end = path.length();
|
|
||||||
int paramIndex = path.indexOf(';', begin);
|
|
||||||
int extIndex = path.lastIndexOf('.', paramIndex != -1 ? paramIndex : end);
|
|
||||||
return new LookupPath(path, extIndex, paramIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getPathWithinApplication(ServerHttpRequest request) {
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
String path = request.getURI().getRawPath();
|
|
||||||
if (!StringUtils.hasText(contextPath)) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
int contextLength = contextPath.length();
|
|
||||||
return (path.length() > contextLength ? path.substring(contextLength) : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String decode(ServerWebExchange exchange, String path) {
|
private String decode(ServerWebExchange exchange, String path) {
|
||||||
// TODO: look up request encoding?
|
// TODO: look up request encoding?
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2017 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.web.server.support;
|
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup path information of an incoming HTTP request.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @since 5.0
|
|
||||||
* @see HttpRequestPathHelper
|
|
||||||
*/
|
|
||||||
public final class LookupPath {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of request attribute under which the LookupPath is stored via
|
|
||||||
* {@link #getOrCreate} and accessed via {@link #getCurrent}.
|
|
||||||
*/
|
|
||||||
public static final String LOOKUP_PATH_ATTRIBUTE_NAME = LookupPath.class.getName();
|
|
||||||
|
|
||||||
|
|
||||||
private final String path;
|
|
||||||
|
|
||||||
private final int fileExtStartIndex;
|
|
||||||
|
|
||||||
private final int fileExtEndIndex;
|
|
||||||
|
|
||||||
|
|
||||||
public LookupPath(String path, int fileExtStartIndex, int fileExtEndIndex) {
|
|
||||||
this.path = path;
|
|
||||||
this.fileExtStartIndex = fileExtStartIndex;
|
|
||||||
this.fileExtEndIndex = fileExtEndIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getPath() {
|
|
||||||
return this.path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPathWithoutExtension() {
|
|
||||||
if (this.fileExtStartIndex != -1) {
|
|
||||||
return this.path.substring(0, this.fileExtStartIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return this.path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getFileExtension() {
|
|
||||||
if (this.fileExtStartIndex == -1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (this.fileExtEndIndex == -1) {
|
|
||||||
return this.path.substring(this.fileExtStartIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return this.path.substring(this.fileExtStartIndex, this.fileExtEndIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the LookupPath for the current request from the request attribute
|
|
||||||
* {@link #LOOKUP_PATH_ATTRIBUTE_NAME} or otherwise create and stored it
|
|
||||||
* under that attribute for subsequent use.
|
|
||||||
* @param exchange the current exchange
|
|
||||||
* @param pathHelper the pathHelper to create the LookupPath with
|
|
||||||
* @return the LookupPath for the current request
|
|
||||||
*/
|
|
||||||
public static LookupPath getOrCreate(ServerWebExchange exchange, HttpRequestPathHelper pathHelper) {
|
|
||||||
return exchange.<LookupPath>getAttribute(LookupPath.LOOKUP_PATH_ATTRIBUTE_NAME)
|
|
||||||
.orElseGet(() -> {
|
|
||||||
LookupPath lookupPath = pathHelper.getLookupPathForRequest(exchange);
|
|
||||||
exchange.getAttributes().put(LookupPath.LOOKUP_PATH_ATTRIBUTE_NAME, lookupPath);
|
|
||||||
return lookupPath;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the LookupPath for the current request from the request attribute
|
|
||||||
* {@link #LOOKUP_PATH_ATTRIBUTE_NAME} or raise an {@link IllegalStateException}
|
|
||||||
* if not found.
|
|
||||||
* @param exchange the current exchange
|
|
||||||
* @return the LookupPath, never {@code null}
|
|
||||||
*/
|
|
||||||
public static LookupPath getCurrent(ServerWebExchange exchange) {
|
|
||||||
return exchange.<LookupPath>getAttribute(LookupPath.LOOKUP_PATH_ATTRIBUTE_NAME)
|
|
||||||
.orElseThrow(() -> new IllegalStateException("No LookupPath attribute."));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -21,8 +21,6 @@ import org.junit.Test;
|
||||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
@ -41,7 +39,6 @@ public class UrlBasedCorsConfigurationSourceTests {
|
||||||
@Test
|
@Test
|
||||||
public void empty() {
|
public void empty() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
assertNull(this.configSource.getCorsConfiguration(exchange));
|
assertNull(this.configSource.getCorsConfiguration(exchange));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,11 +48,9 @@ public class UrlBasedCorsConfigurationSourceTests {
|
||||||
this.configSource.registerCorsConfiguration("/bar/**", config);
|
this.configSource.registerCorsConfiguration("/bar/**", config);
|
||||||
|
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo/test.html").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo/test.html").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
assertNull(this.configSource.getCorsConfiguration(exchange));
|
assertNull(this.configSource.getCorsConfiguration(exchange));
|
||||||
|
|
||||||
exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
|
exchange = MockServerHttpRequest.get("/bar/test.html").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
assertEquals(config, this.configSource.getCorsConfiguration(exchange));
|
assertEquals(config, this.configSource.getCorsConfiguration(exchange));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2017 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.web.server.support;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for {@link LookupPath}
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
public class LookupPathTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parsePath() {
|
|
||||||
LookupPath path = create("/foo");
|
|
||||||
assertEquals("/foo", path.getPath());
|
|
||||||
assertEquals("/foo", path.getPathWithoutExtension());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parsePathWithExtension() {
|
|
||||||
LookupPath path = create("/foo.txt");
|
|
||||||
assertEquals("/foo.txt", path.getPath());
|
|
||||||
assertEquals("/foo", path.getPathWithoutExtension());
|
|
||||||
assertEquals(".txt", path.getFileExtension());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parsePathWithParams() {
|
|
||||||
LookupPath path = create("/test;spring=framework/foo.txt;foo=bar?framework=spring");
|
|
||||||
assertEquals("/test;spring=framework/foo.txt;foo=bar", path.getPath());
|
|
||||||
assertEquals("/test;spring=framework/foo", path.getPathWithoutExtension());
|
|
||||||
assertEquals(".txt", path.getFileExtension());
|
|
||||||
}
|
|
||||||
|
|
||||||
private LookupPath create(String path) {
|
|
||||||
HttpRequestPathHelper helper = new HttpRequestPathHelper();
|
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get(path).build().toExchange();
|
|
||||||
return helper.getLookupPathForRequest(exchange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,7 +28,6 @@ import reactor.core.publisher.Mono;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -101,7 +100,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Object> getHandlerInternal(ServerWebExchange exchange) {
|
public Mono<Object> getHandlerInternal(ServerWebExchange exchange) {
|
||||||
LookupPath lookupPath = LookupPath.getOrCreate(exchange, getPathHelper());
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
Object handler;
|
Object handler;
|
||||||
try {
|
try {
|
||||||
handler = lookupHandler(lookupPath, exchange);
|
handler = lookupHandler(lookupPath, exchange);
|
||||||
|
|
@ -111,10 +110,10 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler != null && logger.isDebugEnabled()) {
|
if (handler != null && logger.isDebugEnabled()) {
|
||||||
logger.debug("Mapping [" + lookupPath.getPath() + "] to " + handler);
|
logger.debug("Mapping [" + lookupPath + "] to " + handler);
|
||||||
}
|
}
|
||||||
else if (handler == null && logger.isTraceEnabled()) {
|
else if (handler == null && logger.isTraceEnabled()) {
|
||||||
logger.trace("No handler mapping found for [" + lookupPath.getPath() + "]");
|
logger.trace("No handler mapping found for [" + lookupPath + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Mono.justOrEmpty(handler);
|
return Mono.justOrEmpty(handler);
|
||||||
|
|
@ -133,29 +132,28 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
* @see org.springframework.web.util.pattern.ParsingPathMatcher
|
* @see org.springframework.web.util.pattern.ParsingPathMatcher
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected Object lookupHandler(LookupPath lookupPath, ServerWebExchange exchange) throws Exception {
|
protected Object lookupHandler(String lookupPath, ServerWebExchange exchange) throws Exception {
|
||||||
// Direct match?
|
// Direct match?
|
||||||
String urlPath = lookupPath.getPath();
|
Object handler = this.handlerMap.get(lookupPath);
|
||||||
Object handler = this.handlerMap.get(urlPath);
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
return handleMatch(handler, urlPath, urlPath, exchange);
|
return handleMatch(handler, lookupPath, lookupPath, exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pattern match?
|
// Pattern match?
|
||||||
List<String> matches = new ArrayList<>();
|
List<String> matches = new ArrayList<>();
|
||||||
for (String pattern : this.handlerMap.keySet()) {
|
for (String pattern : this.handlerMap.keySet()) {
|
||||||
if (getPathMatcher().match(pattern, urlPath)) {
|
if (getPathMatcher().match(pattern, lookupPath)) {
|
||||||
matches.add(pattern);
|
matches.add(pattern);
|
||||||
}
|
}
|
||||||
else if (useTrailingSlashMatch()) {
|
else if (useTrailingSlashMatch()) {
|
||||||
if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", urlPath)) {
|
if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) {
|
||||||
matches.add(pattern +"/");
|
matches.add(pattern +"/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String bestMatch = null;
|
String bestMatch = null;
|
||||||
Comparator<String> comparator = getPathMatcher().getPatternComparator(urlPath);
|
Comparator<String> comparator = getPathMatcher().getPatternComparator(lookupPath);
|
||||||
if (!matches.isEmpty()) {
|
if (!matches.isEmpty()) {
|
||||||
Collections.sort(matches, comparator);
|
Collections.sort(matches, comparator);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
|
|
@ -174,7 +172,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||||
"Could not find handler for best pattern match [" + bestMatch + "]");
|
"Could not find handler for best pattern match [" + bestMatch + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
|
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, lookupPath);
|
||||||
return handleMatch(handler, bestMatch, pathWithinMapping, exchange);
|
return handleMatch(handler, bestMatch, pathWithinMapping, exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import org.springframework.util.PathMatcher;
|
||||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
import org.springframework.web.server.support.HttpRequestPathHelper;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -186,8 +185,8 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
|
||||||
private int getLookupPathIndex(ServerWebExchange exchange) {
|
private int getLookupPathIndex(ServerWebExchange exchange) {
|
||||||
ServerHttpRequest request = exchange.getRequest();
|
ServerHttpRequest request = exchange.getRequest();
|
||||||
String requestPath = request.getURI().getPath();
|
String requestPath = request.getURI().getPath();
|
||||||
LookupPath lookupPath = LookupPath.getOrCreate(exchange, getPathHelper());
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
return requestPath.indexOf(lookupPath.getPath());
|
return requestPath.indexOf(lookupPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getEndPathIndex(String lookupPath) {
|
private int getEndPathIndex(String lookupPath) {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import java.util.Set;
|
||||||
import org.springframework.util.PathMatcher;
|
import org.springframework.util.PathMatcher;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
import org.springframework.web.util.pattern.ParsingPathMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -187,7 +186,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
LookupPath lookupPath = LookupPath.getCurrent(exchange);
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
List<String> matches = getMatchingPatterns(lookupPath);
|
List<String> matches = getMatchingPatterns(lookupPath);
|
||||||
|
|
||||||
return matches.isEmpty() ? null :
|
return matches.isEmpty() ? null :
|
||||||
|
|
@ -204,7 +203,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||||
* @param lookupPath the lookup path to match to existing patterns
|
* @param lookupPath the lookup path to match to existing patterns
|
||||||
* @return a collection of matching patterns sorted with the closest match at the top
|
* @return a collection of matching patterns sorted with the closest match at the top
|
||||||
*/
|
*/
|
||||||
public List<String> getMatchingPatterns(LookupPath lookupPath) {
|
public List<String> getMatchingPatterns(String lookupPath) {
|
||||||
List<String> matches = new ArrayList<>();
|
List<String> matches = new ArrayList<>();
|
||||||
for (String pattern : this.patterns) {
|
for (String pattern : this.patterns) {
|
||||||
String match = getMatchingPattern(pattern, lookupPath);
|
String match = getMatchingPattern(pattern, lookupPath);
|
||||||
|
|
@ -212,33 +211,19 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||||
matches.add(match);
|
matches.add(match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(matches, this.pathMatcher.getPatternComparator(lookupPath.getPath()));
|
Collections.sort(matches, this.pathMatcher.getPatternComparator(lookupPath));
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMatchingPattern(String pattern, LookupPath lookupPath) {
|
private String getMatchingPattern(String pattern, String lookupPath) {
|
||||||
if (pattern.equals(lookupPath.getPath())) {
|
if (pattern.equals(lookupPath)) {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
if (this.useSuffixPatternMatch) {
|
if (this.pathMatcher.match(pattern, lookupPath)) {
|
||||||
if (!this.fileExtensions.isEmpty() && lookupPath.getFileExtension() != null) {
|
|
||||||
if (this.fileExtensions.contains(lookupPath.getFileExtension()) &&
|
|
||||||
this.pathMatcher.match(pattern, lookupPath.getPathWithoutExtension())) {
|
|
||||||
return pattern + lookupPath.getFileExtension();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (lookupPath.getFileExtension() != null
|
|
||||||
&& this.pathMatcher.match(pattern , lookupPath.getPathWithoutExtension())) {
|
|
||||||
return pattern + ".*";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.pathMatcher.match(pattern, lookupPath.getPath())) {
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
if (this.useTrailingSlashMatch) {
|
if (this.useTrailingSlashMatch) {
|
||||||
if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath.getPath())) {
|
if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) {
|
||||||
return pattern +"/";
|
return pattern +"/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,8 +243,8 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(PatternsRequestCondition other, ServerWebExchange exchange) {
|
public int compareTo(PatternsRequestCondition other, ServerWebExchange exchange) {
|
||||||
String path = LookupPath.getCurrent(exchange).getPath();
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(path);
|
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath);
|
||||||
Iterator<String> iterator = this.patterns.iterator();
|
Iterator<String> iterator = this.patterns.iterator();
|
||||||
Iterator<String> iteratorOther = other.patterns.iterator();
|
Iterator<String> iteratorOther = other.patterns.iterator();
|
||||||
while (iterator.hasNext() && iteratorOther.hasNext()) {
|
while (iterator.hasNext() && iteratorOther.hasNext()) {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.reactive.HandlerMapping;
|
import org.springframework.web.reactive.HandlerMapping;
|
||||||
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for {@link HandlerMapping} implementations that define
|
* Abstract base class for {@link HandlerMapping} implementations that define
|
||||||
|
|
@ -258,7 +257,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
|
public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
|
||||||
LookupPath lookupPath = LookupPath.getOrCreate(exchange, getPathHelper());
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Looking up handler method for path " + lookupPath);
|
logger.debug("Looking up handler method for path " + lookupPath);
|
||||||
}
|
}
|
||||||
|
|
@ -295,15 +294,15 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||||
* @param lookupPath the lookup path within the current mapping
|
* @param lookupPath the lookup path within the current mapping
|
||||||
* @param exchange the current exchange
|
* @param exchange the current exchange
|
||||||
* @return the best-matching handler method, or {@code null} if no match
|
* @return the best-matching handler method, or {@code null} if no match
|
||||||
* @see #handleMatch(Object, LookupPath, ServerWebExchange)
|
* @see #handleMatch(Object, String, ServerWebExchange)
|
||||||
* @see #handleNoMatch(Set, LookupPath, ServerWebExchange)
|
* @see #handleNoMatch(Set, String, ServerWebExchange)
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected HandlerMethod lookupHandlerMethod(LookupPath lookupPath, ServerWebExchange exchange)
|
protected HandlerMethod lookupHandlerMethod(String lookupPath, ServerWebExchange exchange)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
List<Match> matches = new ArrayList<Match>();
|
List<Match> matches = new ArrayList<Match>();
|
||||||
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath.getPath());
|
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
|
||||||
if (directPathMatches != null) {
|
if (directPathMatches != null) {
|
||||||
addMatchingMappings(directPathMatches, matches, exchange);
|
addMatchingMappings(directPathMatches, matches, exchange);
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +354,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||||
* @param lookupPath the lookup path within the current mapping
|
* @param lookupPath the lookup path within the current mapping
|
||||||
* @param exchange the current exchange
|
* @param exchange the current exchange
|
||||||
*/
|
*/
|
||||||
protected void handleMatch(T mapping, LookupPath lookupPath, ServerWebExchange exchange) {
|
protected void handleMatch(T mapping, String lookupPath, ServerWebExchange exchange) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -367,7 +366,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
||||||
* @throws Exception provides details that can be translated into an error status code
|
* @throws Exception provides details that can be translated into an error status code
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected HandlerMethod handleNoMatch(Set<T> mappings, LookupPath lookupPath, ServerWebExchange exchange)
|
protected HandlerMethod handleNoMatch(Set<T> mappings, String lookupPath, ServerWebExchange exchange)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
@ -35,9 +34,7 @@ import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.InvalidMediaTypeException;
|
import org.springframework.http.InvalidMediaTypeException;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.reactive.HandlerMapping;
|
import org.springframework.web.reactive.HandlerMapping;
|
||||||
import org.springframework.web.reactive.result.condition.NameValueExpression;
|
import org.springframework.web.reactive.result.condition.NameValueExpression;
|
||||||
|
|
@ -46,7 +43,6 @@ import org.springframework.web.server.NotAcceptableStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.ServerWebInputException;
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -105,30 +101,33 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||||
* @see HandlerMapping#PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
|
* @see HandlerMapping#PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void handleMatch(RequestMappingInfo info, LookupPath lookupPath, ServerWebExchange exchange) {
|
protected void handleMatch(RequestMappingInfo info, String lookupPath, ServerWebExchange exchange) {
|
||||||
super.handleMatch(info, lookupPath, exchange);
|
super.handleMatch(info, lookupPath, exchange);
|
||||||
|
|
||||||
String bestPattern;
|
String bestPattern;
|
||||||
Map<String, String> uriVariables;
|
Map<String, String> uriVariables;
|
||||||
Map<String, String> decodedUriVariables;
|
|
||||||
|
|
||||||
Set<String> patterns = info.getPatternsCondition().getPatterns();
|
Set<String> patterns = info.getPatternsCondition().getPatterns();
|
||||||
if (patterns.isEmpty()) {
|
if (patterns.isEmpty()) {
|
||||||
bestPattern = lookupPath.getPath();
|
bestPattern = lookupPath;
|
||||||
uriVariables = Collections.emptyMap();
|
uriVariables = Collections.emptyMap();
|
||||||
decodedUriVariables = Collections.emptyMap();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bestPattern = patterns.iterator().next();
|
bestPattern = patterns.iterator().next();
|
||||||
uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath.getPath());
|
uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
|
||||||
decodedUriVariables = getPathHelper().decodePathVariables(exchange, uriVariables);
|
}
|
||||||
|
|
||||||
|
// Let URI vars be stripped of semicolon content..
|
||||||
|
Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(exchange, uriVariables);
|
||||||
|
exchange.getAttributes().put(MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
|
||||||
|
|
||||||
|
// Now decode URI variables
|
||||||
|
if (!uriVariables.isEmpty()) {
|
||||||
|
uriVariables = getPathHelper().decodePathVariables(exchange, uriVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
|
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
|
||||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables);
|
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
|
||||||
|
|
||||||
Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(exchange, uriVariables);
|
|
||||||
exchange.getAttributes().put(MATRIX_VARIABLES_ATTRIBUTE, matrixVars);
|
|
||||||
|
|
||||||
if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
|
if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {
|
||||||
Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
|
Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();
|
||||||
|
|
@ -174,7 +173,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||||
* method but not by query parameter conditions
|
* method but not by query parameter conditions
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> infos, LookupPath lookupPath,
|
protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> infos, String lookupPath,
|
||||||
ServerWebExchange exchange) throws Exception {
|
ServerWebExchange exchange) throws Exception {
|
||||||
|
|
||||||
PartialMatchHelper helper = new PartialMatchHelper(infos, exchange);
|
PartialMatchHelper helper = new PartialMatchHelper(infos, exchange);
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||||
import org.springframework.web.reactive.result.HandlerResultHandlerSupport;
|
import org.springframework.web.reactive.result.HandlerResultHandlerSupport;
|
||||||
import org.springframework.web.server.NotAcceptableStatusException;
|
import org.springframework.web.server.NotAcceptableStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code HandlerResultHandler} that encapsulates the view resolution algorithm
|
* {@code HandlerResultHandler} that encapsulates the view resolution algorithm
|
||||||
|
|
@ -259,7 +258,7 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport
|
||||||
* Use the request path the leading and trailing slash stripped.
|
* Use the request path the leading and trailing slash stripped.
|
||||||
*/
|
*/
|
||||||
private String getDefaultViewName(ServerWebExchange exchange) {
|
private String getDefaultViewName(ServerWebExchange exchange) {
|
||||||
String path = LookupPath.getCurrent(exchange).getPath();
|
String path = exchange.getRequest().getPathWithinApplication();
|
||||||
if (path.startsWith("/")) {
|
if (path.startsWith("/")) {
|
||||||
path = path.substring(1);
|
path = path.substring(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,6 @@ public class SimpleUrlHandlerMappingTests {
|
||||||
testUrl("/anotherTest", mainController, handlerMapping, "anotherTest");
|
testUrl("/anotherTest", mainController, handlerMapping, "anotherTest");
|
||||||
testUrl("/stillAnotherTest", null, handlerMapping, null);
|
testUrl("/stillAnotherTest", null, handlerMapping, null);
|
||||||
testUrl("outofpattern*ye", null, handlerMapping, null);
|
testUrl("outofpattern*ye", null, handlerMapping, null);
|
||||||
testUrl("/test%26t%20est/path%26m%20atching.html", null, handlerMapping, null);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testUrl(String url, Object bean, HandlerMapping handlerMapping, String pathWithinMapping) {
|
private void testUrl(String url, Object bean, HandlerMapping handlerMapping, String pathWithinMapping) {
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.web.reactive.result.condition;
|
package org.springframework.web.reactive.result.condition;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
|
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
@ -82,7 +77,7 @@ public class PatternsRequestConditionTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchDirectPath() throws Exception {
|
public void matchDirectPath() throws Exception {
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(initExchange("/foo"));
|
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo").toExchange());
|
||||||
|
|
||||||
assertNotNull(match);
|
assertNotNull(match);
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +85,7 @@ public class PatternsRequestConditionTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchPattern() throws Exception {
|
public void matchPattern() throws Exception {
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo/*");
|
PatternsRequestCondition condition = new PatternsRequestCondition("/foo/*");
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(initExchange("/foo/bar"));
|
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo/bar").toExchange());
|
||||||
|
|
||||||
assertNotNull(match);
|
assertNotNull(match);
|
||||||
}
|
}
|
||||||
|
|
@ -98,69 +93,15 @@ public class PatternsRequestConditionTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchSortPatterns() throws Exception {
|
public void matchSortPatterns() throws Exception {
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/*/*", "/foo/bar", "/foo/*");
|
PatternsRequestCondition condition = new PatternsRequestCondition("/*/*", "/foo/bar", "/foo/*");
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(initExchange("/foo/bar"));
|
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo/bar").toExchange());
|
||||||
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/*/*");
|
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/*/*");
|
||||||
|
|
||||||
assertEquals(expected, match);
|
assertEquals(expected, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchSuffixPattern() throws Exception {
|
|
||||||
ServerWebExchange exchange = initExchange("/foo.html");
|
|
||||||
|
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/{foo}");
|
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
|
|
||||||
|
|
||||||
assertNotNull(match);
|
|
||||||
assertEquals("/{foo}.*", match.getPatterns().iterator().next());
|
|
||||||
|
|
||||||
condition = new PatternsRequestCondition(new String[] {"/{foo}"}, null,false, false, null);
|
|
||||||
match = condition.getMatchingCondition(exchange);
|
|
||||||
|
|
||||||
assertNotNull(match);
|
|
||||||
assertEquals("/{foo}", match.getPatterns().iterator().next());
|
|
||||||
}
|
|
||||||
|
|
||||||
// SPR-8410
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchSuffixPatternUsingFileExtensions() throws Exception {
|
|
||||||
String[] patterns = new String[] {"/jobs/{jobName}"};
|
|
||||||
Set<String> extensions = Collections.singleton("json");
|
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition(patterns, null, true, false, extensions);
|
|
||||||
|
|
||||||
MockServerWebExchange exchange = initExchange("/jobs/my.job");
|
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
|
|
||||||
|
|
||||||
assertNotNull(match);
|
|
||||||
assertEquals("/jobs/{jobName}", match.getPatterns().iterator().next());
|
|
||||||
|
|
||||||
exchange = initExchange("/jobs/my.job.json");
|
|
||||||
match = condition.getMatchingCondition(exchange);
|
|
||||||
|
|
||||||
assertNotNull(match);
|
|
||||||
assertEquals("/jobs/{jobName}.json", match.getPatterns().iterator().next());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchSuffixPatternUsingFileExtensions2() throws Exception {
|
|
||||||
PatternsRequestCondition condition1 = new PatternsRequestCondition(
|
|
||||||
new String[] {"/prefix"}, null, true, false, Collections.singleton("json"));
|
|
||||||
|
|
||||||
PatternsRequestCondition condition2 = new PatternsRequestCondition(
|
|
||||||
new String[] {"/suffix"}, null, true, false, null);
|
|
||||||
|
|
||||||
PatternsRequestCondition combined = condition1.combine(condition2);
|
|
||||||
|
|
||||||
MockServerWebExchange exchange = initExchange("/prefix/suffix.json");
|
|
||||||
PatternsRequestCondition match = combined.getMatchingCondition(exchange);
|
|
||||||
|
|
||||||
assertNotNull(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void matchTrailingSlash() throws Exception {
|
public void matchTrailingSlash() throws Exception {
|
||||||
MockServerWebExchange exchange = initExchange("/foo/");
|
MockServerWebExchange exchange = get("/foo/").toExchange();
|
||||||
|
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
PatternsRequestCondition condition = new PatternsRequestCondition("/foo");
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
|
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
|
||||||
|
|
@ -175,9 +116,8 @@ public class PatternsRequestConditionTests {
|
||||||
assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)",
|
assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)",
|
||||||
"/foo/", match.getPatterns().iterator().next());
|
"/foo/", match.getPatterns().iterator().next());
|
||||||
|
|
||||||
exchange = initExchange("/foo/");
|
|
||||||
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, false, false, null);
|
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, false, false, null);
|
||||||
match = condition.getMatchingCondition(exchange);
|
match = condition.getMatchingCondition(get("/foo/").toExchange());
|
||||||
|
|
||||||
assertNull(match);
|
assertNull(match);
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +125,7 @@ public class PatternsRequestConditionTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchPatternContainsExtension() throws Exception {
|
public void matchPatternContainsExtension() throws Exception {
|
||||||
PatternsRequestCondition condition = new PatternsRequestCondition("/foo.jpg");
|
PatternsRequestCondition condition = new PatternsRequestCondition("/foo.jpg");
|
||||||
PatternsRequestCondition match = condition.getMatchingCondition(initExchange("/foo.html"));
|
PatternsRequestCondition match = condition.getMatchingCondition(get("/foo.html").toExchange());
|
||||||
|
|
||||||
assertNull(match);
|
assertNull(match);
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +135,7 @@ public class PatternsRequestConditionTests {
|
||||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*");
|
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*");
|
||||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo*");
|
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo*");
|
||||||
|
|
||||||
assertEquals(0, c1.compareTo(c2, initExchange("/foo")));
|
assertEquals(0, c1.compareTo(c2, get("/foo").toExchange()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -203,15 +143,15 @@ public class PatternsRequestConditionTests {
|
||||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/fo*");
|
PatternsRequestCondition c1 = new PatternsRequestCondition("/fo*");
|
||||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo");
|
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo");
|
||||||
|
|
||||||
assertEquals(1, c1.compareTo(c2, initExchange("/foo")));
|
assertEquals(1, c1.compareTo(c2, get("/foo").toExchange()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compareNumberOfMatchingPatterns() throws Exception {
|
public void compareNumberOfMatchingPatterns() throws Exception {
|
||||||
ServerWebExchange exchange = initExchange("/foo.html");
|
ServerWebExchange exchange = get("/foo.html").toExchange();
|
||||||
|
|
||||||
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo", "*.jpeg");
|
PatternsRequestCondition c1 = new PatternsRequestCondition("/foo.*", "/foo.jpeg");
|
||||||
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo", "*.html");
|
PatternsRequestCondition c2 = new PatternsRequestCondition("/foo.*", "/foo.html");
|
||||||
|
|
||||||
PatternsRequestCondition match1 = c1.getMatchingCondition(exchange);
|
PatternsRequestCondition match1 = c1.getMatchingCondition(exchange);
|
||||||
PatternsRequestCondition match2 = c2.getMatchingCondition(exchange);
|
PatternsRequestCondition match2 = c2.getMatchingCondition(exchange);
|
||||||
|
|
@ -220,10 +160,4 @@ public class PatternsRequestConditionTests {
|
||||||
assertEquals(1, match1.compareTo(match2, exchange));
|
assertEquals(1, match1.compareTo(match2, exchange));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MockServerWebExchange initExchange(String path) {
|
|
||||||
MockServerWebExchange exchange = get(path).toExchange();
|
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
return exchange;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.reactive.result.method.RequestMappingInfo;
|
import org.springframework.web.reactive.result.method.RequestMappingInfo;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
@ -67,7 +65,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchPatternsCondition() {
|
public void matchPatternsCondition() {
|
||||||
MockServerWebExchange exchange = MockServerHttpRequest.get("/foo").toExchange();
|
MockServerWebExchange exchange = MockServerHttpRequest.get("/foo").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo*", "/bar").build();
|
RequestMappingInfo info = paths("/foo*", "/bar").build();
|
||||||
RequestMappingInfo expected = paths("/foo*").build();
|
RequestMappingInfo expected = paths("/foo*").build();
|
||||||
|
|
@ -83,7 +80,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchParamsCondition() {
|
public void matchParamsCondition() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo?foo=bar").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo?foo=bar").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
||||||
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
||||||
|
|
@ -99,7 +95,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchHeadersCondition() {
|
public void matchHeadersCondition() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").header("foo", "bar").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").header("foo", "bar").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo").headers("foo=bar").build();
|
RequestMappingInfo info = paths("/foo").headers("foo=bar").build();
|
||||||
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
||||||
|
|
@ -115,7 +110,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchConsumesCondition() {
|
public void matchConsumesCondition() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.post("/foo").contentType(MediaType.TEXT_PLAIN).toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.post("/foo").contentType(MediaType.TEXT_PLAIN).toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo").consumes("text/plain").build();
|
RequestMappingInfo info = paths("/foo").consumes("text/plain").build();
|
||||||
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
||||||
|
|
@ -131,7 +125,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchProducesCondition() {
|
public void matchProducesCondition() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").accept(MediaType.TEXT_PLAIN).toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").accept(MediaType.TEXT_PLAIN).toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo").produces("text/plain").build();
|
RequestMappingInfo info = paths("/foo").produces("text/plain").build();
|
||||||
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
||||||
|
|
@ -147,7 +140,6 @@ public class RequestMappingInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void matchCustomCondition() {
|
public void matchCustomCondition() {
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo?foo=bar").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo?foo=bar").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
RequestMappingInfo info = paths("/foo").params("foo=bar").build();
|
||||||
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
RequestMappingInfo match = info.getMatchingCondition(exchange);
|
||||||
|
|
@ -169,7 +161,6 @@ public class RequestMappingInfoTests {
|
||||||
RequestMappingInfo oneMethodOneParam = paths().methods(RequestMethod.GET).params("foo").build();
|
RequestMappingInfo oneMethodOneParam = paths().methods(RequestMethod.GET).params("foo").build();
|
||||||
|
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").toExchange();
|
ServerWebExchange exchange = MockServerHttpRequest.get("/foo").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, exchange);
|
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, exchange);
|
||||||
|
|
||||||
List<RequestMappingInfo> list = asList(none, oneMethod, oneMethodOneParam);
|
List<RequestMappingInfo> list = asList(none, oneMethod, oneMethodOneParam);
|
||||||
|
|
|
||||||
|
|
@ -47,41 +47,41 @@ import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.reactive.BindingContext;
|
import org.springframework.web.reactive.BindingContext;
|
||||||
import org.springframework.web.reactive.HandlerMapping;
|
import org.springframework.web.reactive.HandlerMapping;
|
||||||
import org.springframework.web.reactive.HandlerResult;
|
import org.springframework.web.reactive.HandlerResult;
|
||||||
import org.springframework.web.reactive.result.method.RequestMappingInfo.*;
|
import org.springframework.web.reactive.result.method.RequestMappingInfo.BuilderConfiguration;
|
||||||
import org.springframework.web.server.MethodNotAllowedException;
|
import org.springframework.web.server.MethodNotAllowedException;
|
||||||
import org.springframework.web.server.NotAcceptableStatusException;
|
import org.springframework.web.server.NotAcceptableStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.ServerWebInputException;
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.*;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.*;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.springframework.web.method.MvcAnnotationPredicates.*;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.springframework.web.method.ResolvableMethod.*;
|
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||||
import static org.springframework.web.reactive.result.method.RequestMappingInfo.*;
|
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.method;
|
||||||
|
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||||
|
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
||||||
|
import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
|
||||||
|
import static org.springframework.web.method.MvcAnnotationPredicates.getMapping;
|
||||||
|
import static org.springframework.web.method.MvcAnnotationPredicates.requestMapping;
|
||||||
|
import static org.springframework.web.method.ResolvableMethod.on;
|
||||||
|
import static org.springframework.web.reactive.result.method.RequestMappingInfo.paths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link RequestMappingInfoHandlerMapping}.
|
* Unit tests for {@link RequestMappingInfoHandlerMapping}.
|
||||||
*
|
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class RequestMappingInfoHandlerMappingTests {
|
public class RequestMappingInfoHandlerMappingTests {
|
||||||
|
|
||||||
private TestRequestMappingInfoHandlerMapping handlerMapping;
|
private TestRequestMappingInfoHandlerMapping handlerMapping;
|
||||||
|
|
||||||
private HttpRequestPathHelper pathHelper;
|
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
this.handlerMapping = new TestRequestMappingInfoHandlerMapping();
|
this.handlerMapping = new TestRequestMappingInfoHandlerMapping();
|
||||||
this.handlerMapping.registerHandler(new TestController());
|
this.handlerMapping.registerHandler(new TestController());
|
||||||
this.pathHelper = new HttpRequestPathHelper();
|
|
||||||
this.handlerMapping.setPathHelper(this.pathHelper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -174,7 +174,6 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
public void getHandlerTestMediaTypeNotAcceptable() throws Exception {
|
public void getHandlerTestMediaTypeNotAcceptable() throws Exception {
|
||||||
testMediaTypeNotAcceptable("/persons");
|
testMediaTypeNotAcceptable("/persons");
|
||||||
testMediaTypeNotAcceptable("/persons/");
|
testMediaTypeNotAcceptable("/persons/");
|
||||||
testMediaTypeNotAcceptable("/persons.json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // SPR-12854
|
@Test // SPR-12854
|
||||||
|
|
@ -214,7 +213,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void handleMatchUriTemplateVariables() throws Exception {
|
public void handleMatchUriTemplateVariables() throws Exception {
|
||||||
ServerWebExchange exchange = get("/1/2").toExchange();
|
ServerWebExchange exchange = get("/1/2").toExchange();
|
||||||
LookupPath lookupPath = this.pathHelper.getLookupPathForRequest(exchange);
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
|
|
||||||
RequestMappingInfo key = paths("/{path1}/{path2}").build();
|
RequestMappingInfo key = paths("/{path1}/{path2}").build();
|
||||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||||
|
|
@ -231,12 +230,9 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
public void handleMatchUriTemplateVariablesDecode() throws Exception {
|
public void handleMatchUriTemplateVariablesDecode() throws Exception {
|
||||||
RequestMappingInfo key = paths("/{group}/{identifier}").build();
|
RequestMappingInfo key = paths("/{group}/{identifier}").build();
|
||||||
URI url = URI.create("/group/a%2Fb");
|
URI url = URI.create("/group/a%2Fb");
|
||||||
ServerWebExchange exchange = MockServerHttpRequest.method(HttpMethod.GET, url).toExchange();
|
ServerWebExchange exchange = method(HttpMethod.GET, url).toExchange();
|
||||||
|
|
||||||
this.pathHelper.setUrlDecode(false);
|
|
||||||
LookupPath lookupPath = this.pathHelper.getLookupPathForRequest(exchange);
|
|
||||||
this.handlerMapping.setPathHelper(this.pathHelper);
|
|
||||||
|
|
||||||
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||||
|
|
||||||
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||||
|
|
@ -252,7 +248,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
public void handleMatchBestMatchingPatternAttribute() throws Exception {
|
public void handleMatchBestMatchingPatternAttribute() throws Exception {
|
||||||
RequestMappingInfo key = paths("/{path1}/2", "/**").build();
|
RequestMappingInfo key = paths("/{path1}/2", "/**").build();
|
||||||
ServerWebExchange exchange = get("/1/2").toExchange();
|
ServerWebExchange exchange = get("/1/2").toExchange();
|
||||||
LookupPath lookupPath = this.pathHelper.getLookupPathForRequest(exchange);
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||||
|
|
||||||
assertEquals("/{path1}/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
|
assertEquals("/{path1}/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
|
||||||
|
|
@ -262,7 +258,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
public void handleMatchBestMatchingPatternAttributeNoPatternsDefined() throws Exception {
|
public void handleMatchBestMatchingPatternAttributeNoPatternsDefined() throws Exception {
|
||||||
RequestMappingInfo key = paths().build();
|
RequestMappingInfo key = paths().build();
|
||||||
ServerWebExchange exchange = get("/1/2").toExchange();
|
ServerWebExchange exchange = get("/1/2").toExchange();
|
||||||
LookupPath lookupPath = this.pathHelper.getLookupPathForRequest(exchange);
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||||
|
|
||||||
assertEquals("/1/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
|
assertEquals("/1/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
|
||||||
|
|
@ -309,11 +305,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleMatchMatrixVariablesDecoding() throws Exception {
|
public void handleMatchMatrixVariablesDecoding() throws Exception {
|
||||||
HttpRequestPathHelper urlPathHelper = new HttpRequestPathHelper();
|
ServerWebExchange exchange = method(HttpMethod.GET, URI.create("/path;mvar=a%2fb")).toExchange();
|
||||||
urlPathHelper.setUrlDecode(false);
|
|
||||||
this.handlerMapping.setPathHelper(urlPathHelper);
|
|
||||||
|
|
||||||
ServerWebExchange exchange = get("/path;mvar=a%2fb").toExchange();
|
|
||||||
handleMatch(exchange, "/path{filter}");
|
handleMatch(exchange, "/path{filter}");
|
||||||
|
|
||||||
MultiValueMap<String, String> matrixVariables = getMatrixVariables(exchange, "filter");
|
MultiValueMap<String, String> matrixVariables = getMatrixVariables(exchange, "filter");
|
||||||
|
|
@ -375,7 +367,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||||
|
|
||||||
private void handleMatch(ServerWebExchange exchange, String pattern) {
|
private void handleMatch(ServerWebExchange exchange, String pattern) {
|
||||||
RequestMappingInfo info = paths(pattern).build();
|
RequestMappingInfo info = paths(pattern).build();
|
||||||
LookupPath lookupPath = this.pathHelper.getLookupPathForRequest(exchange);
|
String lookupPath = exchange.getRequest().getPathWithinApplication();
|
||||||
this.handlerMapping.handleMatch(info, lookupPath, exchange);
|
this.handlerMapping.handleMatch(info, lookupPath, exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,6 @@ import org.springframework.web.reactive.accept.HeaderContentTypeResolver;
|
||||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||||
import org.springframework.web.server.NotAcceptableStatusException;
|
import org.springframework.web.server.NotAcceptableStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
|
||||||
import org.springframework.web.server.support.LookupPath;
|
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
@ -219,17 +217,14 @@ public class ViewResolutionResultHandlerTests {
|
||||||
ViewResolutionResultHandler handler = resultHandler(new TestViewResolver("account"));
|
ViewResolutionResultHandler handler = resultHandler(new TestViewResolver("account"));
|
||||||
|
|
||||||
MockServerWebExchange exchange = get("/account").toExchange();
|
MockServerWebExchange exchange = get("/account").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
||||||
assertResponseBody(exchange, "account: {id=123}");
|
assertResponseBody(exchange, "account: {id=123}");
|
||||||
|
|
||||||
exchange = get("/account/").toExchange();
|
exchange = get("/account/").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
||||||
assertResponseBody(exchange, "account: {id=123}");
|
assertResponseBody(exchange, "account: {id=123}");
|
||||||
|
|
||||||
exchange = get("/account.123").toExchange();
|
exchange = get("/account.123").toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
handler.handleResult(exchange, result).block(Duration.ofMillis(5000));
|
||||||
assertResponseBody(exchange, "account: {id=123}");
|
assertResponseBody(exchange, "account: {id=123}");
|
||||||
}
|
}
|
||||||
|
|
@ -256,7 +251,6 @@ public class ViewResolutionResultHandlerTests {
|
||||||
HandlerResult handlerResult = new HandlerResult(new Object(), value, returnType, this.bindingContext);
|
HandlerResult handlerResult = new HandlerResult(new Object(), value, returnType, this.bindingContext);
|
||||||
|
|
||||||
MockServerWebExchange exchange = get("/account").accept(APPLICATION_JSON).toExchange();
|
MockServerWebExchange exchange = get("/account").accept(APPLICATION_JSON).toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
|
|
||||||
TestView defaultView = new TestView("jsonView", APPLICATION_JSON);
|
TestView defaultView = new TestView("jsonView", APPLICATION_JSON);
|
||||||
|
|
||||||
|
|
@ -328,7 +322,6 @@ public class ViewResolutionResultHandlerTests {
|
||||||
model.addAttribute("id", "123");
|
model.addAttribute("id", "123");
|
||||||
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType, this.bindingContext);
|
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType, this.bindingContext);
|
||||||
MockServerWebExchange exchange = get(path).toExchange();
|
MockServerWebExchange exchange = get(path).toExchange();
|
||||||
LookupPath.getOrCreate(exchange, new HttpRequestPathHelper());
|
|
||||||
resultHandler(resolvers).handleResult(exchange, result).block(Duration.ofSeconds(5));
|
resultHandler(resolvers).handleResult(exchange, result).block(Duration.ofSeconds(5));
|
||||||
assertResponseBody(exchange, responseBody);
|
assertResponseBody(exchange, responseBody);
|
||||||
return exchange;
|
return exchange;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
/reservation.html=mainController
|
/reservation.html=mainController
|
||||||
/payment.html=mainController
|
/payment.html=mainController
|
||||||
/confirmation.html=mainController
|
/confirmation.html=mainController
|
||||||
/test%26t%20est/path%26m%20atching.html=mainController
|
|
||||||
</value>
|
</value>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue