From 07b961caa66ec181126e6f2b108637edaf8c19ae Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Tue, 26 Sep 2017 10:46:25 +0200 Subject: [PATCH] Empty path should match the "/" PathPattern This commit makes both slash "/" and empty "" request paths match the "/" `PathPattern`. Issue: SPR-15653 --- .../web/util/pattern/PathPattern.java | 13 ++++++++++--- .../web/util/pattern/PathPatternTests.java | 7 ++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java b/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java index 738b03e824..6493523fa8 100644 --- a/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java +++ b/spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java @@ -156,7 +156,6 @@ public class PathPattern implements Comparable { return this.patternString; } - /** * Whether this pattern matches the given path. * @param pathContainer the candidate path to attempt to match against @@ -164,7 +163,8 @@ public class PathPattern implements Comparable { */ public boolean matches(PathContainer pathContainer) { if (this.head == null) { - return !hasLength(pathContainer); + return !hasLength(pathContainer) || + (this.matchOptionalTrailingSeparator && pathContainerIsJustSeparator(pathContainer)); } else if (!hasLength(pathContainer)) { if (this.head instanceof WildcardTheRestPathElement || this.head instanceof CaptureTheRestPathElement) { @@ -187,7 +187,9 @@ public class PathPattern implements Comparable { @Nullable public PathMatchInfo matchAndExtract(PathContainer pathContainer) { if (this.head == null) { - return hasLength(pathContainer) ? null : PathMatchInfo.EMPTY; + return hasLength(pathContainer) && + !(this.matchOptionalTrailingSeparator && pathContainerIsJustSeparator(pathContainer)) + ? null : PathMatchInfo.EMPTY; } else if (!hasLength(pathContainer)) { if (this.head instanceof WildcardTheRestPathElement || this.head instanceof CaptureTheRestPathElement) { @@ -708,5 +710,10 @@ public class PathPattern implements Comparable { private static int scoreByNormalizedLength(PathPattern pattern) { return -pattern.getNormalizedLength(); } + + private boolean pathContainerIsJustSeparator(PathContainer pathContainer) { + return pathContainer.value().length() == 1 && + pathContainer.value().charAt(0) == separator; + } } diff --git a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java index bc82ea94cf..32f8db3458 100644 --- a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java @@ -77,6 +77,7 @@ public class PathPatternTests { @Test public void basicMatching() { checkMatches("", ""); + checkMatches("", "/"); checkMatches("", null); checkNoMatch("/abc", "/"); checkMatches("/", "/"); @@ -1113,9 +1114,13 @@ public class PathPatternTests { result = matchAndExtract("/abc/{var}","/abc/one"); assertEquals("one",result.getUriVariables().get("var")); assertNull(result.getMatrixVariables().get("var")); + + result = matchAndExtract("",""); + assertNotNull(result); + result = matchAndExtract("","/"); + assertNotNull(result); } - private PathPattern.PathMatchInfo matchAndExtract(String pattern, String path) { return parse(pattern).matchAndExtract(PathPatternTests.toPathContainer(path)); }