Skip to content

Commit e753b53

Browse files
committed
EndpointRequest should match links with trailing slash
Fixes gh-13921
1 parent f7b90a7 commit e753b53

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ private String getPathPrefix(WebApplicationContext context) {
157157
protected abstract RequestMatcher createDelegate(WebApplicationContext context,
158158
RequestMatcherFactory requestMatcherFactory);
159159

160+
protected List<RequestMatcher> getLinksMatchers(
161+
RequestMatcherFactory requestMatcherFactory, String basePath) {
162+
List<RequestMatcher> linksMatchers = new ArrayList<>();
163+
linksMatchers.add(requestMatcherFactory.antPath(basePath));
164+
linksMatchers.add(requestMatcherFactory.antPath(basePath, "/"));
165+
return linksMatchers;
166+
}
167+
160168
}
161169

162170
/**
@@ -220,10 +228,10 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
220228
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove);
221229
List<RequestMatcher> delegateMatchers = getDelegateMatchers(
222230
requestMatcherFactory, paths);
223-
if (this.includeLinks
224-
&& StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
225-
delegateMatchers.add(
226-
requestMatcherFactory.antPath(pathMappedEndpoints.getBasePath()));
231+
String basePath = pathMappedEndpoints.getBasePath();
232+
if (this.includeLinks && StringUtils.hasText(basePath)) {
233+
delegateMatchers
234+
.addAll(getLinksMatchers(requestMatcherFactory, basePath));
227235
}
228236
return new OrRequestMatcher(delegateMatchers);
229237
}
@@ -271,8 +279,10 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
271279
RequestMatcherFactory requestMatcherFactory) {
272280
WebEndpointProperties properties = context
273281
.getBean(WebEndpointProperties.class);
274-
if (StringUtils.hasText(properties.getBasePath())) {
275-
return requestMatcherFactory.antPath(properties.getBasePath());
282+
String basePath = properties.getBasePath();
283+
if (StringUtils.hasText(basePath)) {
284+
return new OrRequestMatcher(
285+
getLinksMatchers(requestMatcherFactory, basePath));
276286
}
277287
return EMPTY_MATCHER;
278288
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ public void toAnyEndpointShouldMatchEndpointPath() {
5959
assertMatcher(matcher).matches("/actuator");
6060
}
6161

62+
@Test
63+
public void toAnyEndpointShouldMatchEndpointPathWithTrailingSlash() {
64+
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint();
65+
assertMatcher(matcher).matches("/actuator/foo/");
66+
assertMatcher(matcher).matches("/actuator/bar/");
67+
assertMatcher(matcher).matches("/actuator/");
68+
}
69+
6270
@Test
6371
public void toAnyEndpointWhenBasePathIsEmptyShouldNotMatchLinks() {
6472
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint();
@@ -104,6 +112,7 @@ public void toLinksShouldOnlyMatchLinks() {
104112
assertMatcher(matcher).doesNotMatch("/actuator/foo");
105113
assertMatcher(matcher).doesNotMatch("/actuator/bar");
106114
assertMatcher(matcher).matches("/actuator");
115+
assertMatcher(matcher).matches("/actuator/");
107116
}
108117

109118
@Test

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,20 @@ public class EndpointRequestTests {
5454
public void toAnyEndpointShouldMatchEndpointPath() {
5555
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
5656
assertMatcher(matcher, "/actuator", "/").matches("/actuator/foo");
57+
assertMatcher(matcher, "/actuator", "/").matches("/actuator/foo/zoo/");
5758
assertMatcher(matcher, "/actuator", "/").matches("/actuator/bar");
59+
assertMatcher(matcher, "/actuator", "/").matches("/actuator/bar/baz");
5860
assertMatcher(matcher, "/actuator", "/").matches("/actuator");
5961
}
6062

63+
@Test
64+
public void toAnyEndpointShouldMatchEndpointPathWithTrailingSlash() {
65+
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
66+
assertMatcher(matcher, "/actuator", "/").matches("/actuator/foo/");
67+
assertMatcher(matcher, "/actuator", "/").matches("/actuator/bar/");
68+
assertMatcher(matcher, "/actuator", "/").matches("/actuator/");
69+
}
70+
6171
@Test
6272
public void toAnyEndpointWhenBasePathIsEmptyShouldNotMatchLinks() {
6373
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
@@ -127,6 +137,7 @@ public void toLinksShouldOnlyMatchLinks() {
127137
assertMatcher(matcher).doesNotMatch("/actuator/foo");
128138
assertMatcher(matcher).doesNotMatch("/actuator/bar");
129139
assertMatcher(matcher).matches("/actuator");
140+
assertMatcher(matcher).matches("/actuator/");
130141
}
131142

132143
@Test

0 commit comments

Comments
 (0)