Allow EndpointRequest matching without path bean
Update `EndpointRequest` to that the `PathMappedEndpoints` bean is optional. A missing bean is treated as if there are no path mapped endpoints. Fixes gh-12238
This commit is contained in:
@@ -29,6 +29,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.security.reactive.ApplicationContextServerWebExchangeMatcher;
|
||||
@@ -36,6 +37,7 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.security.web.server.util.matcher.OrServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@@ -48,6 +50,9 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
*/
|
||||
public final class EndpointRequest {
|
||||
|
||||
private static final ServerWebExchangeMatcher EMPTY_MATCHER = (request) -> MatchResult
|
||||
.notMatch();
|
||||
|
||||
private EndpointRequest() {
|
||||
}
|
||||
|
||||
@@ -134,19 +139,34 @@ public final class EndpointRequest {
|
||||
|
||||
@Override
|
||||
protected void initialized(Supplier<PathMappedEndpoints> pathMappedEndpoints) {
|
||||
this.delegate = createDelegate(pathMappedEndpoints);
|
||||
}
|
||||
|
||||
private ServerWebExchangeMatcher createDelegate(
|
||||
Supplier<PathMappedEndpoints> pathMappedEndpoints) {
|
||||
try {
|
||||
return createDelegate(pathMappedEndpoints.get());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return EMPTY_MATCHER;
|
||||
}
|
||||
}
|
||||
|
||||
private ServerWebExchangeMatcher createDelegate(
|
||||
PathMappedEndpoints pathMappedEndpoints) {
|
||||
Set<String> paths = new LinkedHashSet<>();
|
||||
if (this.includes.isEmpty()) {
|
||||
paths.addAll(pathMappedEndpoints.get().getAllPaths());
|
||||
paths.addAll(pathMappedEndpoints.getAllPaths());
|
||||
}
|
||||
streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add);
|
||||
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove);
|
||||
this.delegate = new OrServerWebExchangeMatcher(getDelegateMatchers(paths));
|
||||
return new OrServerWebExchangeMatcher(getDelegateMatchers(paths));
|
||||
}
|
||||
|
||||
private Stream<String> streamPaths(List<Object> source,
|
||||
Supplier<PathMappedEndpoints> pathMappedEndpoints) {
|
||||
PathMappedEndpoints pathMappedEndpoints) {
|
||||
return source.stream().filter(Objects::nonNull).map(this::getEndpointId)
|
||||
.map(pathMappedEndpoints.get()::getPath);
|
||||
.map(pathMappedEndpoints::getPath);
|
||||
}
|
||||
|
||||
private String getEndpointId(Object source) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
|
||||
@@ -48,6 +49,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class EndpointRequest {
|
||||
|
||||
private static final RequestMatcher EMPTY_MATCHER = (request) -> false;
|
||||
|
||||
private EndpointRequest() {
|
||||
}
|
||||
|
||||
@@ -131,13 +134,27 @@ public final class EndpointRequest {
|
||||
|
||||
@Override
|
||||
protected void initialized(Supplier<PathMappedEndpoints> pathMappedEndpoints) {
|
||||
this.delegate = createDelegate(pathMappedEndpoints);
|
||||
}
|
||||
|
||||
private RequestMatcher createDelegate(
|
||||
Supplier<PathMappedEndpoints> pathMappedEndpoints) {
|
||||
try {
|
||||
return createDelegate(pathMappedEndpoints.get());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
return EMPTY_MATCHER;
|
||||
}
|
||||
}
|
||||
|
||||
private RequestMatcher createDelegate(PathMappedEndpoints pathMappedEndpoints) {
|
||||
Set<String> paths = new LinkedHashSet<>();
|
||||
if (this.includes.isEmpty()) {
|
||||
paths.addAll(pathMappedEndpoints.get().getAllPaths());
|
||||
paths.addAll(pathMappedEndpoints.getAllPaths());
|
||||
}
|
||||
streamPaths(this.includes, pathMappedEndpoints.get()).forEach(paths::add);
|
||||
streamPaths(this.excludes, pathMappedEndpoints.get()).forEach(paths::remove);
|
||||
this.delegate = new OrRequestMatcher(getDelegateMatchers(paths));
|
||||
streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add);
|
||||
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove);
|
||||
return new OrRequestMatcher(getDelegateMatchers(paths));
|
||||
}
|
||||
|
||||
private Stream<String> streamPaths(List<Object> source,
|
||||
|
||||
@@ -102,6 +102,13 @@ public class EndpointRequestTests {
|
||||
assertMatcher(matcher).matches("/actuator/bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noEndpointPathsBeansShouldNeverMatch() {
|
||||
ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint();
|
||||
assertMatcher(matcher, null).doesNotMatch("/actuator/foo");
|
||||
assertMatcher(matcher, null).doesNotMatch("/actuator/bar");
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher) {
|
||||
return assertMatcher(matcher, mockPathMappedEndpoints());
|
||||
}
|
||||
@@ -123,7 +130,9 @@ public class EndpointRequestTests {
|
||||
private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher,
|
||||
PathMappedEndpoints pathMappedEndpoints) {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
|
||||
if (pathMappedEndpoints != null) {
|
||||
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
|
||||
}
|
||||
return assertThat(new RequestMatcherAssert(context, matcher));
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,13 @@ public class EndpointRequestTests {
|
||||
assertMatcher(matcher).matches("/actuator/bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noEndpointPathsBeansShouldNeverMatch() {
|
||||
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
|
||||
assertMatcher(matcher, null).doesNotMatch("/actuator/foo");
|
||||
assertMatcher(matcher, null).doesNotMatch("/actuator/bar");
|
||||
}
|
||||
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher) {
|
||||
return assertMatcher(matcher, mockPathMappedEndpoints());
|
||||
}
|
||||
@@ -119,7 +126,9 @@ public class EndpointRequestTests {
|
||||
private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
|
||||
PathMappedEndpoints pathMappedEndpoints) {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
|
||||
if (pathMappedEndpoints != null) {
|
||||
context.registerBean(PathMappedEndpoints.class, () -> pathMappedEndpoints);
|
||||
}
|
||||
return assertThat(new RequestMatcherAssert(context, matcher));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user