diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java index ceec49afdcd5..63c9b6e7efe2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java @@ -316,6 +316,8 @@ public EndpointServerWebExchangeMatcher excludingLinks() { /** * Restricts the matcher to only consider requests with a particular http method. + *

+ * The links endpoint, if included, is always matched using {@code GET}. * @param httpMethod the http method to include * @return a copy of the matcher further restricted to only match requests with * the specified http method @@ -373,9 +375,9 @@ protected ServerWebExchangeMatcher createDelegate(WebEndpointProperties properti String linksPath = getLinksPath(properties.getBasePath()); if (linksPath != null) { List linksMatchers = new ArrayList<>(); - linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath)); + linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath, HttpMethod.GET)); if (!linksPath.endsWith("/")) { - linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath + "/")); + linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath + "/", HttpMethod.GET)); } return new OrServerWebExchangeMatcher(linksMatchers); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java index e41be1933e12..ab6117cbd6b2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java @@ -227,9 +227,9 @@ protected final List getDelegateMatchers(RequestMatcherFactory r protected List getLinksMatchers(RequestMatcherFactory requestMatcherFactory, RequestMatcherProvider matcherProvider, String linksPath) { List linksMatchers = new ArrayList<>(); - linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, linksPath)); + linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, HttpMethod.GET, linksPath)); if (!linksPath.endsWith("/")) { - linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, linksPath, "/")); + linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, HttpMethod.GET, linksPath, "/")); } return linksMatchers; } @@ -350,6 +350,8 @@ public EndpointRequestMatcher excludingLinks() { /** * Restricts the matcher to only consider requests with a particular HTTP method. + *

+ * The links endpoint, if included, is always matched using {@code GET}. * @param httpMethod the HTTP method to include * @return a copy of the matcher further restricted to only match requests with * the specified HTTP method diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java index 3bc3fba059fe..a7a7ab6fefba 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java @@ -75,6 +75,15 @@ void toAnyEndpointWithHttpMethodShouldRespectRequestMethod() { assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.GET, "/actuator/foo"); } + @Test + void toAnyEndpointWithHttpMethodShouldUseGetForLinks() { + ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint().withHttpMethod(HttpMethod.POST); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator"); + assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.POST, "/actuator"); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator/"); + assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.POST, "/actuator/"); + } + @Test void toAnyEndpointShouldMatchEndpointPathWithTrailingSlash() { ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint(); @@ -140,8 +149,10 @@ void toLinksShouldOnlyMatchLinks() { ServerWebExchangeMatcher matcher = EndpointRequest.toLinks(); assertMatcher(matcher).doesNotMatch("/actuator/foo"); assertMatcher(matcher).doesNotMatch("/actuator/bar"); - assertMatcher(matcher).matches("/actuator"); - assertMatcher(matcher).matches("/actuator/"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator"); + assertMatcher(matcher).doesNotMatch(HttpMethod.POST, "/actuator"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator/"); + assertMatcher(matcher).doesNotMatch(HttpMethod.POST, "/actuator/"); } @Test diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java index 75e266d5ed08..96f69112d8f2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java @@ -64,7 +64,7 @@ void toAnyEndpointShouldMatchEndpointPath() { assertMatcher(matcher, "/actuator").matches("/actuator/foo/zoo/"); assertMatcher(matcher, "/actuator").matches("/actuator/bar"); assertMatcher(matcher, "/actuator").matches("/actuator/bar/baz"); - assertMatcher(matcher, "/actuator").matches("/actuator"); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator"); } @Test @@ -75,12 +75,22 @@ void toAnyEndpointWithHttpMethodShouldRespectRequestMethod() { assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.GET, "/actuator/foo"); } + @Test + void toAnyEndpointWithHttpMethodShouldUseGetForLinks() { + EndpointRequest.EndpointRequestMatcher matcher = EndpointRequest.toAnyEndpoint() + .withHttpMethod(HttpMethod.POST); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator"); + assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.POST, "/actuator"); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator/"); + assertMatcher(matcher, "/actuator").doesNotMatch(HttpMethod.POST, "/actuator/"); + } + @Test void toAnyEndpointShouldMatchEndpointPathWithTrailingSlash() { RequestMatcher matcher = EndpointRequest.toAnyEndpoint(); assertMatcher(matcher, "/actuator").matches("/actuator/foo/"); assertMatcher(matcher, "/actuator").matches("/actuator/bar/"); - assertMatcher(matcher, "/actuator").matches("/actuator/"); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator/"); } @Test @@ -97,7 +107,7 @@ void toAnyEndpointWhenBasePathIsEmptyAndManagementPortDifferentShouldMatchLinks( RequestMatcher matcher = EndpointRequest.toAnyEndpoint(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), null, WebServerNamespace.MANAGEMENT); - assertMatcher.matches("/"); + assertMatcher.matches(HttpMethod.GET, "/"); assertMatcher.matches("/foo"); } @@ -112,7 +122,7 @@ void toAnyEndpointWhenDispatcherServletPathProviderNotAvailableUsesEmptyPath() { RequestMatcher matcher = EndpointRequest.toAnyEndpoint(); assertMatcher(matcher, "/actuator").matches("/actuator/foo"); assertMatcher(matcher, "/actuator").matches("/actuator/bar"); - assertMatcher(matcher, "/actuator").matches("/actuator"); + assertMatcher(matcher, "/actuator").matches(HttpMethod.GET, "/actuator"); assertMatcher(matcher, "/actuator").doesNotMatch("/actuator/baz"); } @@ -147,8 +157,10 @@ void toLinksShouldOnlyMatchLinks() { RequestMatcher matcher = EndpointRequest.toLinks(); assertMatcher(matcher).doesNotMatch("/actuator/foo"); assertMatcher(matcher).doesNotMatch("/actuator/bar"); - assertMatcher(matcher).matches("/actuator"); - assertMatcher(matcher).matches("/actuator/"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator"); + assertMatcher(matcher).doesNotMatch(HttpMethod.POST, "/actuator"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator/"); + assertMatcher(matcher).doesNotMatch(HttpMethod.POST, "/actuator/"); } @Test @@ -165,7 +177,7 @@ void toLinksWhenBasePathEmptyAndManagementPortDifferentShouldMatchRoot() { RequestMatcher matcher = EndpointRequest.toLinks(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), null, WebServerNamespace.MANAGEMENT); - assertMatcher.matches("/"); + assertMatcher.matches(HttpMethod.GET, "/"); assertMatcher.doesNotMatch("/foo"); } @@ -180,7 +192,7 @@ void excludeByClassShouldNotMatchExcluded() { assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/foo"); assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/baz"); assertMatcher(matcher).matches("/actuator/bar"); - assertMatcher(matcher).matches("/actuator"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator"); } @Test @@ -195,7 +207,7 @@ void excludeByIdShouldNotMatchExcluded() { RequestMatcher matcher = EndpointRequest.toAnyEndpoint().excluding("foo"); assertMatcher(matcher).doesNotMatch("/actuator/foo"); assertMatcher(matcher).matches("/actuator/bar"); - assertMatcher(matcher).matches("/actuator"); + assertMatcher(matcher).matches(HttpMethod.GET, "/actuator"); } @Test