Allow separator configuration in PathPatternParser
This commit allows to configure a custom path separator when parsing and matching path patterns with `PathPatternParser`, but also when parsing incoming paths as `PathContainer` instances. Closes gh-23092
This commit is contained in:
parent
ec91934730
commit
33becd8258
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -89,11 +89,13 @@ final class DefaultPathContainer implements PathContainer {
|
|||
}
|
||||
|
||||
|
||||
static PathContainer createFromUrlPath(String path) {
|
||||
static PathContainer createFromUrlPath(String path, String separator) {
|
||||
if (path.equals("")) {
|
||||
return EMPTY_PATH;
|
||||
}
|
||||
String separator = "/";
|
||||
if (separator.length() == 0) {
|
||||
throw new IllegalArgumentException("separator should not be empty");
|
||||
}
|
||||
Separator separatorElement = separator.equals(SEPARATOR.value()) ? SEPARATOR : () -> separator;
|
||||
List<Element> elements = new ArrayList<>();
|
||||
int begin;
|
||||
|
|
|
@ -66,13 +66,25 @@ public interface PathContainer {
|
|||
|
||||
|
||||
/**
|
||||
* Parse the path value into a sequence of {@link Separator Separator} and
|
||||
* {@link PathSegment PathSegment} elements.
|
||||
* @param path the encoded, raw URL path value to parse
|
||||
* Parse the path value into a sequence of {@code "/"} {@link Separator Separator}
|
||||
* and {@link PathSegment PathSegment} elements.
|
||||
* @param path the encoded, raw path value to parse
|
||||
* @return the parsed path
|
||||
*/
|
||||
static PathContainer parsePath(String path) {
|
||||
return DefaultPathContainer.createFromUrlPath(path);
|
||||
return DefaultPathContainer.createFromUrlPath(path, "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the path value into a sequence of {@link Separator Separator} and
|
||||
* {@link PathSegment PathSegment} elements.
|
||||
* @param path the encoded, raw path value to parse
|
||||
* @param separator the decoded separator for parsing patterns
|
||||
* @return the parsed path
|
||||
* @since 5.2
|
||||
*/
|
||||
static PathContainer parsePath(String path, String separator) {
|
||||
return DefaultPathContainer.createFromUrlPath(path, separator);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -36,6 +36,8 @@ public class PathPatternParser {
|
|||
|
||||
private boolean caseSensitive = true;
|
||||
|
||||
private char separator = '/';
|
||||
|
||||
|
||||
/**
|
||||
* Whether a {@link PathPattern} produced by this parser should should
|
||||
|
@ -75,14 +77,20 @@ public class PathPatternParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Accessor used for the separator to use.
|
||||
* <p>Currently not exposed for configuration with URI path patterns and
|
||||
* mainly for use in InternalPathPatternParser and PathPattern. If required
|
||||
* in the future, a similar option would also need to be exposed in
|
||||
* {@link org.springframework.http.server.PathContainer PathContainer}.
|
||||
* Char that represents the separator to use in the patterns.
|
||||
* <p>The default is {@code '/'}.
|
||||
* @since 5.2
|
||||
*/
|
||||
char getSeparator() {
|
||||
return '/';
|
||||
public void setSeparator(char separator) {
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Char that represents the separator to use in the patterns.
|
||||
* @since 5.2
|
||||
*/
|
||||
public char getSeparator() {
|
||||
return this.separator;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.util.LinkedMultiValueMap;
|
|||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultPathContainer}.
|
||||
|
@ -111,15 +112,18 @@ public class DefaultPathContainerTests {
|
|||
testPath("//%20/%20", "//%20/%20", Arrays.asList("/", "/", "%20", "/", "%20"));
|
||||
}
|
||||
|
||||
private void testPath(String input, String value, List<String> expectedElements) {
|
||||
|
||||
PathContainer path = PathContainer.parsePath(input);
|
||||
private void testPath(String input, String separator, String value, List<String> expectedElements) {
|
||||
PathContainer path = PathContainer.parsePath(input, separator);
|
||||
|
||||
assertThat(path.value()).as("value: '" + input + "'").isEqualTo(value);
|
||||
assertThat(path.elements().stream()
|
||||
.map(PathContainer.Element::value).collect(Collectors.toList())).as("elements: " + input).isEqualTo(expectedElements);
|
||||
}
|
||||
|
||||
private void testPath(String input, String value, List<String> expectedElements) {
|
||||
testPath(input, "/", value, expectedElements);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subPath() throws Exception {
|
||||
// basic
|
||||
|
@ -137,4 +141,14 @@ public class DefaultPathContainerTests {
|
|||
assertThat(path.subPath(2).value()).isEqualTo("/b/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathWithCustomSeparator() throws Exception {
|
||||
testPath("a.b.c", ".", "a.b.c", Arrays.asList("a", ".", "b", ".", "c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptySeparator() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PathContainer.parsePath("path", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -408,6 +408,15 @@ public class PathPatternParserTests {
|
|||
assertThat(patterns.get(1)).isEqualTo(p2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void separatorTests() {
|
||||
PathPatternParser parser = new PathPatternParser();
|
||||
parser.setSeparator('.');
|
||||
String rawPattern = "first.second.{last}";
|
||||
PathPattern pattern = parser.parse(rawPattern);
|
||||
assertThat(pattern.computePatternString()).isEqualTo(rawPattern);
|
||||
}
|
||||
|
||||
private PathPattern parse(String pattern) {
|
||||
PathPatternParser patternParser = new PathPatternParser();
|
||||
return patternParser.parse(pattern);
|
||||
|
|
Loading…
Reference in New Issue