Browse Source

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
pull/23098/head
Brian Clozel 6 years ago
parent
commit
33becd8258
  1. 8
      spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java
  2. 18
      spring-web/src/main/java/org/springframework/http/server/PathContainer.java
  3. 24
      spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternParser.java
  4. 20
      spring-web/src/test/java/org/springframework/http/server/DefaultPathContainerTests.java
  5. 9
      spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java

8
spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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;

18
spring-web/src/main/java/org/springframework/http/server/PathContainer.java

@ -65,14 +65,26 @@ public interface PathContainer { @@ -65,14 +65,26 @@ public interface PathContainer {
}
/**
* 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, "/");
}
/**
* 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
* @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) {
return DefaultPathContainer.createFromUrlPath(path);
static PathContainer parsePath(String path, String separator) {
return DefaultPathContainer.createFromUrlPath(path, separator);
}

24
spring-web/src/main/java/org/springframework/web/util/pattern/PathPatternParser.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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 { @@ -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
*/
public void setSeparator(char separator) {
this.separator = separator;
}
/**
* Char that represents the separator to use in the patterns.
* @since 5.2
*/
char getSeparator() {
return '/';
public char getSeparator() {
return this.separator;
}

20
spring-web/src/test/java/org/springframework/http/server/DefaultPathContainerTests.java

@ -27,6 +27,7 @@ import org.springframework.util.LinkedMultiValueMap; @@ -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 { @@ -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 { @@ -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", ""));
}
}

9
spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java

@ -408,6 +408,15 @@ public class PathPatternParserTests { @@ -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…
Cancel
Save