Skip to content

Commit d924538

Browse files
committed
Fix RegexPathElement when matching variables against a root path
The first fix for issue 15264 covered the case of using a single variable (the case mentioned in the bug report). However, when more than one variable is used a different PathElement is built. This RegexPathElement needs a similar change that checks the path includes data to bind. Issue: SPR-15264
1 parent 9829a62 commit d924538

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

spring-web/src/main/java/org/springframework/web/util/patterns/RegexPathElement.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ public boolean matches(int candidateIndex, MatchingContext matchingContext) {
125125
if (matches) {
126126
if (next == null) {
127127
// No more pattern, is there more data?
128-
matches = (p == matchingContext.candidateLength);
128+
// If pattern is capturing variables there must be some actual data to bind to them
129+
matches = (p == matchingContext.candidateLength &&
130+
((this.variableNames.size() == 0) ? true : p > candidateIndex));
129131
}
130132
else {
131133
if (matchingContext.isMatchStartMatching && p == matchingContext.candidateLength) {

spring-web/src/test/java/org/springframework/web/util/patterns/PathPatternMatcherTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.junit.Rule;
2727
import org.junit.Test;
2828
import org.junit.rules.ExpectedException;
29+
import org.springframework.util.AntPathMatcher;
2930

3031
import static org.hamcrest.CoreMatchers.*;
3132
import static org.junit.Assert.*;
@@ -524,12 +525,40 @@ public void extractUriTemplateVariables_spr15264() {
524525
assertTrue(pp.matches("/abc/boo"));
525526
assertTrue(pp.matches("/a/boo"));
526527
assertFalse(pp.matches("//boo"));
528+
529+
pp = parse("/{foo}*");
530+
assertTrue(pp.matches("/abc"));
531+
assertFalse(pp.matches("/"));
527532

528533
checkCapture("/{word:[a-z]*}", "/abc", "word", "abc");
529534
pp = parse("/{word:[a-z]*}");
530535
assertFalse(pp.matches("/1"));
531536
assertTrue(pp.matches("/a"));
532537
assertFalse(pp.matches("/"));
538+
539+
// Two captures mean we use a RegexPathElement
540+
pp = new PathPatternParser().parse("/{foo}{bar}");
541+
assertTrue(pp.matches("/abcdef"));
542+
assertFalse(pp.matches("/"));
543+
assertFalse(pp.matches("//"));
544+
checkCapture("/{foo:[a-z][a-z]}{bar:[a-z]}", "/abc", "foo", "ab", "bar", "c");
545+
546+
// Only patterns not capturing variables cannot match against just /
547+
pp = new PathPatternParser().parse("/****");
548+
assertTrue(pp.matches("/abcdef"));
549+
assertTrue(pp.matches("/"));
550+
assertTrue(pp.matches("//"));
551+
552+
// Confirming AntPathMatcher behaviour:
553+
assertFalse(new AntPathMatcher().match("/{foo}", "/"));
554+
assertTrue(new AntPathMatcher().match("/{foo}", "/a"));
555+
assertTrue(new AntPathMatcher().match("/{foo}{bar}", "/a"));
556+
assertFalse(new AntPathMatcher().match("/{foo}*", "/"));
557+
assertTrue(new AntPathMatcher().match("/*", "/"));
558+
assertFalse(new AntPathMatcher().match("/*{foo}", "/"));
559+
Map<String, String> vars = new AntPathMatcher().extractUriTemplateVariables("/{foo}{bar}", "/a");
560+
assertEquals("a",vars.get("foo"));
561+
assertEquals("",vars.get("bar"));
533562
}
534563

535564
@Test

0 commit comments

Comments
 (0)