Skip to content

Commit 4c258b9

Browse files
therepanicjzheaux
authored andcommitted
A Root basePath No Longer Creates a Double-Slash
Closes gh-17812 Signed-off-by: Andrey Litvitski <[email protected]>
1 parent 653f22d commit 4c258b9

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* </p>
5050
*
5151
* @author Josh Cummings
52+
* @author Andrey Litvitski
5253
* @since 6.5
5354
*/
5455
public final class PathPatternRequestMatcher implements RequestMatcher {
@@ -200,14 +201,15 @@ public static final class Builder {
200201
*
201202
* <p>
202203
* Prefixes should be of the form {@code /my/prefix}, starting with a slash, not
203-
* ending in a slash, and not containing and wildcards
204+
* ending in a slash, and not containing and wildcards The special value
205+
* {@code "/"} may be used to indicate the root context.
204206
* @param basePath the path prefix
205207
* @return the {@link Builder} for more configuration
206208
*/
207209
public Builder basePath(String basePath) {
208210
Assert.notNull(basePath, "basePath cannot be null");
209211
Assert.isTrue(basePath.startsWith("/"), "basePath must start with '/'");
210-
Assert.isTrue(!basePath.endsWith("/"), "basePath must not end with a slash");
212+
Assert.isTrue("/".equals(basePath) || !basePath.endsWith("/"), "basePath must not end with a slash");
211213
Assert.isTrue(!basePath.contains("*"), "basePath must not contain a star");
212214
return new Builder(this.parser, basePath);
213215
}
@@ -282,7 +284,8 @@ public PathPatternRequestMatcher matcher(String path) {
282284
public PathPatternRequestMatcher matcher(@Nullable HttpMethod method, String path) {
283285
Assert.notNull(path, "pattern cannot be null");
284286
Assert.isTrue(path.startsWith("/"), "pattern must start with a /");
285-
PathPattern pathPattern = this.parser.parse(this.basePath + path);
287+
String prefix = ("/".equals(this.basePath)) ? "" : this.basePath;
288+
PathPattern pathPattern = this.parser.parse(prefix + path);
286289
return new PathPatternRequestMatcher(pathPattern,
287290
(method != null) ? new HttpMethodRequestMatcher(method) : AnyRequestMatcher.INSTANCE);
288291
}

web/src/test/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcherTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ void servletPathWhenEndsWithSlashOrStarThenIllegalArgument() {
137137
.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().basePath("/path/"));
138138
}
139139

140+
@Test
141+
void matcherWhenBasePathIsRootThenNoDoubleSlash() {
142+
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults().basePath("/");
143+
RequestMatcher matcher = builder.matcher(HttpMethod.GET, "/path");
144+
MockHttpServletRequest mock = get("/path").servletPath("/path").buildRequest(null);
145+
assertThat(matcher.matches(mock)).isTrue();
146+
}
147+
140148
MockHttpServletRequest request(String uri) {
141149
MockHttpServletRequest request = new MockHttpServletRequest("GET", uri);
142150
ServletRequestPathUtils.parseAndCache(request);

0 commit comments

Comments
 (0)