Fix AntPathMatcher URI template variable extractor

See gh-33085
This commit is contained in:
tafjwr 2024-06-22 18:16:31 +09:00 committed by Brian Clozel
parent 9b58e1ff71
commit 83fcdfba64
2 changed files with 26 additions and 9 deletions

View File

@ -462,7 +462,7 @@ public class AntPathMatcher implements PathMatcher {
matcher = this.stringMatcherCache.get(pattern); matcher = this.stringMatcherCache.get(pattern);
} }
if (matcher == null) { if (matcher == null) {
matcher = new AntPathStringMatcher(pattern, this.caseSensitive); matcher = new AntPathStringMatcher(pattern, this.pathSeparator, this.caseSensitive);
if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) { if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {
// Try to adapt to the runtime situation that we're encountering: // Try to adapt to the runtime situation that we're encountering:
// There are obviously too many different patterns coming in here... // There are obviously too many different patterns coming in here...
@ -646,8 +646,6 @@ public class AntPathMatcher implements PathMatcher {
*/ */
protected static class AntPathStringMatcher { protected static class AntPathStringMatcher {
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)"; private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
private final String rawPattern; private final String rawPattern;
@ -661,15 +659,11 @@ public class AntPathMatcher implements PathMatcher {
private final List<String> variableNames = new ArrayList<>(); private final List<String> variableNames = new ArrayList<>();
public AntPathStringMatcher(String pattern) { public AntPathStringMatcher(String pattern, String pathSeparator, boolean caseSensitive) {
this(pattern, true);
}
public AntPathStringMatcher(String pattern, boolean caseSensitive) {
this.rawPattern = pattern; this.rawPattern = pattern;
this.caseSensitive = caseSensitive; this.caseSensitive = caseSensitive;
StringBuilder patternBuilder = new StringBuilder(); StringBuilder patternBuilder = new StringBuilder();
Matcher matcher = GLOB_PATTERN.matcher(pattern); Matcher matcher = getGlobPattern(pathSeparator).matcher(pattern);
int end = 0; int end = 0;
while (matcher.find()) { while (matcher.find()) {
patternBuilder.append(quote(pattern, end, matcher.start())); patternBuilder.append(quote(pattern, end, matcher.start()));
@ -710,6 +704,10 @@ public class AntPathMatcher implements PathMatcher {
} }
} }
private static Pattern getGlobPattern(String pathSeparator) {
return Pattern.compile(String.format("\\?|\\*|\\{((?:\\{[^%s]+?\\}|[^%s{}]|\\\\[{}])+?)\\}", pathSeparator, pathSeparator));
}
private String quote(String s, int start, int end) { private String quote(String s, int start, int end) {
if (start == end) { if (start == end) {
return ""; return "";

View File

@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class AntPathMatcherTests { class AntPathMatcherTests {
private final AntPathMatcher pathMatcher = new AntPathMatcher(); private final AntPathMatcher pathMatcher = new AntPathMatcher();
private final AntPathMatcher dotSeparatedPathMatcher = new AntPathMatcher(".");
@Test @Test
@ -357,6 +358,24 @@ class AntPathMatcherTests {
assertThat(result).isEqualTo(expected); assertThat(result).isEqualTo(expected);
} }
@Test // gh-26264
void extractUriTemplateVariablesFromDotSeparatedPath() {
Map<String, String> result = dotSeparatedPathMatcher.extractUriTemplateVariables("price.stock.{tickerSymbol}", "price.stock.aaa");
assertThat(result).isEqualTo(Collections.singletonMap("tickerSymbol", "aaa"));
result = dotSeparatedPathMatcher.extractUriTemplateVariables("price.stock.{ticker/symbol}", "price.stock.aaa");
assertThat(result).isEqualTo(Collections.singletonMap("ticker/symbol", "aaa"));
result = dotSeparatedPathMatcher.extractUriTemplateVariables("notification.**.{operation}", "notification.foo.update");
assertThat(result).isEqualTo(Collections.singletonMap("operation", "update"));
result = dotSeparatedPathMatcher.extractUriTemplateVariables("news.sports.feed/{type}", "news.sports.feed/xml");
assertThat(result).isEqualTo(Collections.singletonMap("type", "xml"));
result = dotSeparatedPathMatcher.extractUriTemplateVariables("news.sports.{operation}/*", "news.sports.feed/xml");
assertThat(result).isEqualTo(Collections.singletonMap("operation", "feed"));
}
@Test @Test
void extractUriTemplateVariablesRegex() { void extractUriTemplateVariablesRegex() {
Map<String, String> result = pathMatcher Map<String, String> result = pathMatcher