diff --git a/spring-web/src/main/java/org/springframework/web/server/support/HttpRequestPathHelper.java b/spring-web/src/main/java/org/springframework/web/server/support/HttpRequestPathHelper.java deleted file mode 100644 index 2b4f00c7e89..00000000000 --- a/spring-web/src/main/java/org/springframework/web/server/support/HttpRequestPathHelper.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2002-2016 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 java.io.UnsupportedEncodingException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.StringTokenizer; - -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.StringUtils; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.UriUtils; - -/** - * A helper class to obtain the lookup path for path matching purposes. - * - * @author Rossen Stoyanchev - * @since 5.0 - */ -public class HttpRequestPathHelper { - - private boolean urlDecode = false; - - - // TODO: sanitize path, default/request encoding?, remove path params? - - /** - * Set if the request path should be URL-decoded. - *

Default is "true". - * @see UriUtils#decode(String, String) - */ - public void setUrlDecode(boolean urlDecode) { - this.urlDecode = urlDecode; - } - - /** - * Whether the request path should be URL decoded. - */ - public boolean shouldUrlDecode() { - return this.urlDecode; - } - - - private String decode(ServerWebExchange exchange, String path) { - // TODO: look up request encoding? - try { - return UriUtils.decode(path, "UTF-8"); - } - catch (UnsupportedEncodingException ex) { - // Should not happen - throw new IllegalStateException("Could not decode request string [" + path + "]"); - } - } - - /** - * Decode the given URI path variables unless {@link #setUrlDecode(boolean)} - * is set to {@code true} in which case it is assumed the URL path from - * which the variables were extracted is already decoded through a call to - * {@link #getLookupPathForRequest(ServerWebExchange)}. - * @param exchange current exchange - * @param vars URI variables extracted from the URL path - * @return the same Map or a new Map instance - */ - public Map decodePathVariables(ServerWebExchange exchange, Map vars) { - if (this.urlDecode) { - return vars; - } - Map decodedVars = new LinkedHashMap<>(vars.size()); - for (Map.Entry entry : vars.entrySet()) { - decodedVars.put(entry.getKey(), decode(exchange, entry.getValue())); - } - return decodedVars; - } - - /** - * Parse the given string with matrix variables. An example string would look - * like this {@code "q1=a;q1=b;q2=a,b,c"}. The resulting map would contain - * keys {@code "q1"} and {@code "q2"} with values {@code ["a","b"]} and - * {@code ["a","b","c"]} respectively. - *

The returned values are decoded unless {@link #setUrlDecode(boolean)} - * is set to {@code true} in which case it is assumed the URL path from - * which the variables were extracted is already decoded through a call to - * {@link #getLookupPathForRequest(ServerWebExchange)}. - * @param semicolonContent path parameter content to parse - * @return a map with matrix variable names and values (never {@code null}) - */ - public MultiValueMap parseMatrixVariables(ServerWebExchange exchange, - String semicolonContent) { - - MultiValueMap result = new LinkedMultiValueMap<>(); - if (!StringUtils.hasText(semicolonContent)) { - return result; - } - StringTokenizer pairs = new StringTokenizer(semicolonContent, ";"); - while (pairs.hasMoreTokens()) { - String pair = pairs.nextToken(); - int index = pair.indexOf('='); - if (index != -1) { - String name = pair.substring(0, index); - String rawValue = pair.substring(index + 1); - for (String value : StringUtils.commaDelimitedListToStringArray(rawValue)) { - result.add(name, value); - } - } - else { - result.add(pair, ""); - } - } - return decodeMatrixVariables(exchange, result); - } - - /** - * Decode the given matrix variables unless {@link #setUrlDecode(boolean)} - * is set to {@code true} in which case it is assumed the URL path from - * which the variables were extracted is already decoded through a call to - * {@link #getLookupPathForRequest(ServerWebExchange)}. - * @param exchange current exchange - * @param vars URI variables extracted from the URL path - * @return the same Map or a new Map instance - */ - private MultiValueMap decodeMatrixVariables(ServerWebExchange exchange, - MultiValueMap vars) { - - if (this.urlDecode) { - return vars; - } - MultiValueMap decodedVars = new LinkedMultiValueMap<>(vars.size()); - for (String key : vars.keySet()) { - for (String value : vars.get(key)) { - decodedVars.add(key, decode(exchange, value)); - } - } - return decodedVars; - } - -} diff --git a/spring-web/src/main/java/org/springframework/web/server/support/package-info.java b/spring-web/src/main/java/org/springframework/web/server/support/package-info.java deleted file mode 100644 index 93a8f728717..00000000000 --- a/spring-web/src/main/java/org/springframework/web/server/support/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Helper classes on top of {@code org.springframework.web.server}, - * as a convenience for working with {@code ServerWebExchange}. - */ -@NonNullApi -package org.springframework.web.server.support; - -import org.springframework.lang.NonNullApi; diff --git a/spring-web/src/test/java/org/springframework/web/server/support/HttpRequestPathHelperTests.java b/spring-web/src/test/java/org/springframework/web/server/support/HttpRequestPathHelperTests.java deleted file mode 100644 index 6721a18ae99..00000000000 --- a/spring-web/src/test/java/org/springframework/web/server/support/HttpRequestPathHelperTests.java +++ /dev/null @@ -1,82 +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 java.util.Arrays; - -import org.junit.Test; - -import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ServerWebExchange; - -import static org.junit.Assert.assertEquals; - -/** - * Unit tests for {@link HttpRequestPathHelper}. - * @author Rossen Stoyanchev - */ -public class HttpRequestPathHelperTests { - - - @Test - public void parseMatrixVariables() { - - HttpRequestPathHelper pathHelper = new HttpRequestPathHelper(); - ServerWebExchange exchange = MockServerHttpRequest.get("").toExchange(); - MultiValueMap variables; - - variables = pathHelper.parseMatrixVariables(exchange, null); - assertEquals(0, variables.size()); - - variables = pathHelper.parseMatrixVariables(exchange, "year"); - assertEquals(1, variables.size()); - assertEquals("", variables.getFirst("year")); - - variables = pathHelper.parseMatrixVariables(exchange, "year=2012"); - assertEquals(1, variables.size()); - assertEquals("2012", variables.getFirst("year")); - - variables = pathHelper.parseMatrixVariables(exchange, "year=2012;colors=red,blue,green"); - assertEquals(2, variables.size()); - assertEquals(Arrays.asList("red", "blue", "green"), variables.get("colors")); - assertEquals("2012", variables.getFirst("year")); - - variables = pathHelper.parseMatrixVariables(exchange, ";year=2012;colors=red,blue,green;"); - assertEquals(2, variables.size()); - assertEquals(Arrays.asList("red", "blue", "green"), variables.get("colors")); - assertEquals("2012", variables.getFirst("year")); - - variables = pathHelper.parseMatrixVariables(exchange, "colors=red;colors=blue;colors=green"); - assertEquals(1, variables.size()); - assertEquals(Arrays.asList("red", "blue", "green"), variables.get("colors")); - } - - @Test - public void parseMatrixVariablesAndDecode() { - - HttpRequestPathHelper pathHelper = new HttpRequestPathHelper(); - pathHelper.setUrlDecode(false); - - ServerWebExchange exchange = MockServerHttpRequest.get("").toExchange(); - MultiValueMap variables; - - variables = pathHelper.parseMatrixVariables(exchange, "mvar=a%2fb"); - assertEquals(1, variables.size()); - assertEquals("a/b", variables.getFirst("mvar")); - } - -} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/PathMatchConfigurer.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/PathMatchConfigurer.java index 8ef10b5f8da..16a7f3f137f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/PathMatchConfigurer.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/PathMatchConfigurer.java @@ -18,7 +18,6 @@ package org.springframework.web.reactive.config; import org.springframework.lang.Nullable; import org.springframework.util.PathMatcher; -import org.springframework.web.server.support.HttpRequestPathHelper; import org.springframework.web.util.pattern.ParsingPathMatcher; /** @@ -35,8 +34,6 @@ public class PathMatchConfigurer { private Boolean registeredSuffixPatternMatch; - private HttpRequestPathHelper pathHelper; - private PathMatcher pathMatcher; @@ -73,15 +70,6 @@ public class PathMatchConfigurer { return this; } - /** - * Set a {@code HttpRequestPathHelper} for the resolution of lookup paths. - *

Default is {@code HttpRequestPathHelper}. - */ - public PathMatchConfigurer setPathHelper(HttpRequestPathHelper pathHelper) { - this.pathHelper = pathHelper; - return this; - } - /** * Set the PathMatcher for matching URL paths against registered URL patterns. *

The default is a {@link org.springframework.web.util.pattern.ParsingPathMatcher}. @@ -106,11 +94,6 @@ public class PathMatchConfigurer { return this.registeredSuffixPatternMatch; } - @Nullable - protected HttpRequestPathHelper getPathHelper() { - return this.pathHelper; - } - @Nullable public PathMatcher getPathMatcher() { if (this.pathMatcher instanceof ParsingPathMatcher && (this.trailingSlashMatch || this.suffixPatternMatch)) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java index a3fd8c31bfa..e3b5b719537 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java @@ -133,16 +133,10 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { if (useTrailingSlashMatch != null) { mapping.setUseTrailingSlashMatch(useTrailingSlashMatch); } - - HttpRequestPathHelper pathHelper = configurer.getPathHelper(); - if (pathHelper != null) { - mapping.setPathHelper(pathHelper); - } PathMatcher pathMatcher = configurer.getPathMatcher(); if (pathMatcher != null) { mapping.setPathMatcher(pathMatcher); } - return mapping; } @@ -251,9 +245,6 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { if (pathMatchConfigurer.getPathMatcher() != null) { handlerMapping.setPathMatcher(pathMatchConfigurer.getPathMatcher()); } - if (pathMatchConfigurer.getPathHelper() != null) { - handlerMapping.setPathHelper(pathMatchConfigurer.getPathHelper()); - } } else { handlerMapping = new EmptyHandlerMapping(); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java index dbc362c4516..6bbaabaa92d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java @@ -34,7 +34,6 @@ import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; -import org.springframework.web.server.support.HttpRequestPathHelper; import org.springframework.web.util.pattern.ParsingPathMatcher; /** @@ -53,8 +52,6 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport im private int order = Integer.MAX_VALUE; // default: same as non-Ordered - private HttpRequestPathHelper pathHelper = new HttpRequestPathHelper(); - private PathMatcher pathMatcher = new ParsingPathMatcher(); private final UrlBasedCorsConfigurationSource globalCorsConfigSource = new UrlBasedCorsConfigurationSource(); @@ -76,33 +73,6 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport im return this.order; } - /** - * Set if the path should be URL-decoded. This sets the same property on the - * underlying path helper. - * @see HttpRequestPathHelper#setUrlDecode(boolean) - */ - public void setUrlDecode(boolean urlDecode) { - this.pathHelper.setUrlDecode(urlDecode); - } - - /** - * Set the {@link HttpRequestPathHelper} to use for resolution of lookup - * paths. Use this to override the default implementation with a custom - * subclass or to share common path helper settings across multiple - * HandlerMappings. - */ - public void setPathHelper(HttpRequestPathHelper pathHelper) { - this.pathHelper = pathHelper; - } - - /** - * Return the {@link HttpRequestPathHelper} implementation to use for - * resolution of lookup paths. - */ - public HttpRequestPathHelper getPathHelper() { - return this.pathHelper; - } - /** * Set the PathMatcher implementation to use for matching URL paths * against registered URL patterns. diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java index b60259ade61..856c9c95829 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java @@ -37,7 +37,6 @@ import org.springframework.lang.Nullable; import org.springframework.util.PathMatcher; import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.support.HttpRequestPathHelper; import org.springframework.web.util.pattern.ParsingPathMatcher; /** @@ -55,8 +54,6 @@ public class ResourceUrlProvider implements ApplicationListener handlerMap = new LinkedHashMap<>(); @@ -64,22 +61,6 @@ public class ResourceUrlProvider implements ApplicationListener StringUtils.uriDecode(e.getValue(), StandardCharsets.UTF_8) + )); } exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern); @@ -156,11 +162,41 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe semicolonContent = uriVarValue.substring(semicolonIndex + 1); uriVariables.put(uriVar.getKey(), uriVarValue.substring(0, semicolonIndex)); } - result.put(uriVar.getKey(), getPathHelper().parseMatrixVariables(exchange, semicolonContent)); + result.put(uriVar.getKey(), parseMatrixVariables(exchange, semicolonContent)); } return result; } + private static MultiValueMap parseMatrixVariables(ServerWebExchange exchange, + String semicolonContent) { + + MultiValueMap vars = new LinkedMultiValueMap<>(); + if (!StringUtils.hasText(semicolonContent)) { + return vars; + } + StringTokenizer pairs = new StringTokenizer(semicolonContent, ";"); + while (pairs.hasMoreTokens()) { + String pair = pairs.nextToken(); + int index = pair.indexOf('='); + if (index != -1) { + String name = pair.substring(0, index); + String rawValue = pair.substring(index + 1); + for (String value : StringUtils.commaDelimitedListToStringArray(rawValue)) { + vars.add(name, value); + } + } + else { + vars.add(pair, ""); + } + } + MultiValueMap decoded = new LinkedMultiValueMap<>(vars.size()); + vars.forEach((key, values) -> values.forEach(value -> { + String decodedValue = StringUtils.uriDecode(value, StandardCharsets.UTF_8); + decoded.add(key, decodedValue); + })); + return decoded; + } + /** * Iterate all RequestMappingInfos once again, look if any match by URL at * least and raise exceptions accordingly. diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java index a58186d6eaf..15bbb639816 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java @@ -63,7 +63,11 @@ import org.springframework.web.reactive.result.view.freemarker.FreeMarkerViewRes import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; import static org.springframework.core.ResolvableType.forClass; import static org.springframework.core.ResolvableType.forClassWithGenerics; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED; @@ -250,7 +254,6 @@ public class WebFluxConfigurationSupportTests { assertEquals(Ordered.LOWEST_PRECEDENCE - 1, handlerMapping.getOrder()); - assertNotNull(handlerMapping.getPathHelper()); assertNotNull(handlerMapping.getPathMatcher()); SimpleUrlHandlerMapping urlHandlerMapping = (SimpleUrlHandlerMapping) handlerMapping; diff --git a/spring-webflux/src/test/resources/org/springframework/web/reactive/handler/map.xml b/spring-webflux/src/test/resources/org/springframework/web/reactive/handler/map.xml index 74b2a7af612..7990d5bdf85 100644 --- a/spring-webflux/src/test/resources/org/springframework/web/reactive/handler/map.xml +++ b/spring-webflux/src/test/resources/org/springframework/web/reactive/handler/map.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - welcome.html=mainController