Browse Source
The use of the undecoded URL path by default and the removal of suffix pattern matching effectively means HttpRequestPathHelper is no longer needed. Issue: SPR-15640, SPR-15639pull/1457/head
10 changed files with 43 additions and 323 deletions
@ -1,153 +0,0 @@
@@ -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. |
||||
* <p>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<String, String> decodePathVariables(ServerWebExchange exchange, Map<String, String> vars) { |
||||
if (this.urlDecode) { |
||||
return vars; |
||||
} |
||||
Map<String, String> decodedVars = new LinkedHashMap<>(vars.size()); |
||||
for (Map.Entry<String, String> 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. |
||||
* <p>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<String, String> parseMatrixVariables(ServerWebExchange exchange, |
||||
String semicolonContent) { |
||||
|
||||
MultiValueMap<String, String> 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<String, String> decodeMatrixVariables(ServerWebExchange exchange, |
||||
MultiValueMap<String, String> vars) { |
||||
|
||||
if (this.urlDecode) { |
||||
return vars; |
||||
} |
||||
MultiValueMap<String, String> decodedVars = new LinkedMultiValueMap<>(vars.size()); |
||||
for (String key : vars.keySet()) { |
||||
for (String value : vars.get(key)) { |
||||
decodedVars.add(key, decode(exchange, value)); |
||||
} |
||||
} |
||||
return decodedVars; |
||||
} |
||||
|
||||
} |
||||
@ -1,8 +0,0 @@
@@ -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; |
||||
@ -1,82 +0,0 @@
@@ -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<String, String> 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<String, String> variables; |
||||
|
||||
variables = pathHelper.parseMatrixVariables(exchange, "mvar=a%2fb"); |
||||
assertEquals(1, variables.size()); |
||||
assertEquals("a/b", variables.getFirst("mvar")); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue