Skip to content

Commit c25a9c2

Browse files
committed
Fix EndpointRequest.toLinks() not matching when base-path is '/'
When management.endpoints.web.base-path is set to "/", cleanBasePath() stripped it to "", making LinksRequestMatcher return EMPTY_MATCHER (always false). Preserve "/" as a valid base path and avoid producing "//" patterns in link matchers. Fixes gh-34834
1 parent d70d6e8 commit c25a9c2

File tree

6 files changed

+27
-5
lines changed

6 files changed

+27
-5
lines changed

module/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointProperties.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void setBasePath(String basePath) {
6767
}
6868

6969
private String cleanBasePath(String basePath) {
70-
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
70+
if (StringUtils.hasText(basePath) && basePath.endsWith("/") && basePath.length() > 1) {
7171
return basePath.substring(0, basePath.length() - 1);
7272
}
7373
return basePath;

module/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointPropertiesTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void defaultBasePathShouldBeApplication() {
3838
void basePathShouldBeCleaned() {
3939
WebEndpointProperties properties = new WebEndpointProperties();
4040
properties.setBasePath("/");
41-
assertThat(properties.getBasePath()).isEmpty();
41+
assertThat(properties.getBasePath()).isEqualTo("/");
4242
properties.setBasePath("/actuator/");
4343
assertThat(properties.getBasePath()).isEqualTo("/actuator");
4444
}

module/spring-boot-security/src/main/java/org/springframework/boot/security/autoconfigure/actuate/web/reactive/EndpointRequest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,13 @@ private LinksServerWebExchangeMatcher() {
371371
@Override
372372
protected ServerWebExchangeMatcher createDelegate(WebEndpointProperties properties) {
373373
if (StringUtils.hasText(properties.getBasePath())) {
374+
String basePath = properties.getBasePath();
375+
if (basePath.endsWith("/")) {
376+
return new PathPatternParserServerWebExchangeMatcher(basePath);
377+
}
374378
return new OrServerWebExchangeMatcher(
375-
new PathPatternParserServerWebExchangeMatcher(properties.getBasePath()),
376-
new PathPatternParserServerWebExchangeMatcher(properties.getBasePath() + "/"));
379+
new PathPatternParserServerWebExchangeMatcher(basePath),
380+
new PathPatternParserServerWebExchangeMatcher(basePath + "/"));
377381
}
378382
return EMPTY_MATCHER;
379383
}

module/spring-boot-security/src/main/java/org/springframework/boot/security/autoconfigure/actuate/web/servlet/EndpointRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ protected List<RequestMatcher> getLinksMatchers(RequestMatcherFactory requestMat
227227
RequestMatcherProvider matcherProvider, String basePath) {
228228
List<RequestMatcher> linksMatchers = new ArrayList<>();
229229
linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, basePath));
230-
linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, basePath, "/"));
230+
if (!basePath.endsWith("/")) {
231+
linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, basePath, "/"));
232+
}
231233
return linksMatchers;
232234
}
233235

module/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/web/reactive/EndpointRequestTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ void toLinksWhenBasePathEmptyShouldNotMatch() {
145145
assertMatcher.doesNotMatch("/");
146146
}
147147

148+
@Test
149+
void toLinksWhenBasePathIsRootShouldMatch() {
150+
ServerWebExchangeMatcher matcher = EndpointRequest.toLinks();
151+
RequestMatcherAssert assertMatcher = assertMatcher(matcher, "/");
152+
assertMatcher.matches("/");
153+
assertMatcher.doesNotMatch("/foo");
154+
}
155+
148156
@Test
149157
void excludeByClassShouldNotMatchExcluded() {
150158
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint()

module/spring-boot-security/src/test/java/org/springframework/boot/security/autoconfigure/actuate/web/servlet/EndpointRequestTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ void toLinksWhenBasePathEmptyShouldNotMatch() {
151151
assertMatcher.doesNotMatch("/");
152152
}
153153

154+
@Test
155+
void toLinksWhenBasePathIsRootShouldMatch() {
156+
RequestMatcher matcher = EndpointRequest.toLinks();
157+
RequestMatcherAssert assertMatcher = assertMatcher(matcher, "/");
158+
assertMatcher.matches("/");
159+
assertMatcher.doesNotMatch("/foo");
160+
}
161+
154162
@Test
155163
void excludeByClassShouldNotMatchExcluded() {
156164
RequestMatcher matcher = EndpointRequest.toAnyEndpoint().excluding(FooEndpoint.class, BazServletEndpoint.class);

0 commit comments

Comments
 (0)