From 1c0253b380323e69b5f586295fa36ad476e82fa4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 10 Feb 2025 09:28:28 +0000 Subject: [PATCH] Align reactive EndpointRequest with servlet equivalent Closes gh-44189 --- .../security/reactive/EndpointRequest.java | 17 +++++++---- .../reactive/EndpointRequestTests.java | 28 +++++++++++++++++-- 2 files changed, 36 insertions(+), 9 deletions(-) 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 16e91c6e906..ac538c616c8 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; import org.springframework.boot.security.reactive.ApplicationContextServerWebExchangeMatcher; +import org.springframework.boot.web.context.WebServerApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; @@ -211,11 +212,15 @@ public final class EndpointRequest { protected final boolean hasWebServerNamespace(ApplicationContext applicationContext, WebServerNamespace webServerNamespace) { - if (applicationContext.getParent() == null) { - return WebServerNamespace.SERVER.equals(webServerNamespace); - } - String parentContextId = applicationContext.getParent().getId(); - return applicationContext.getId().equals(parentContextId + ":" + webServerNamespace); + return WebServerApplicationContext.hasServerNamespace(applicationContext, webServerNamespace.getValue()) + || hasImplicitServerNamespace(applicationContext, webServerNamespace); + } + + private boolean hasImplicitServerNamespace(ApplicationContext applicationContext, + WebServerNamespace webServerNamespace) { + return WebServerNamespace.SERVER.equals(webServerNamespace) + && WebServerApplicationContext.getServerNamespace(applicationContext) == null + && applicationContext.getParent() == null; } protected final String toString(List endpoints, String emptyValue) { 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 792ed54ca9c..8443b276a09 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 @@ -32,12 +32,15 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.WebServer; import org.springframework.context.support.StaticApplicationContext; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpResponse; import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; +import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; import org.springframework.web.server.adapter.HttpWebHandlerAdapter; @@ -315,10 +318,8 @@ class EndpointRequestTests { PathMappedEndpoints pathMappedEndpoints, WebServerNamespace namespace) { StaticApplicationContext context = new StaticApplicationContext(); if (namespace != null && !WebServerNamespace.SERVER.equals(namespace)) { - StaticApplicationContext parentContext = new StaticApplicationContext(); - parentContext.setId("app"); + NamedStaticWebApplicationContext parentContext = new NamedStaticWebApplicationContext(namespace); context.setParent(parentContext); - context.setId(parentContext.getId() + ":" + namespace); } context.registerBean(WebEndpointProperties.class); if (pathMappedEndpoints != null) { @@ -351,6 +352,27 @@ class EndpointRequestTests { return endpoint; } + static class NamedStaticWebApplicationContext extends StaticWebApplicationContext + implements WebServerApplicationContext { + + private final WebServerNamespace webServerNamespace; + + NamedStaticWebApplicationContext(WebServerNamespace webServerNamespace) { + this.webServerNamespace = webServerNamespace; + } + + @Override + public WebServer getWebServer() { + return null; + } + + @Override + public String getServerNamespace() { + return (this.webServerNamespace != null) ? this.webServerNamespace.getValue() : null; + } + + } + static class RequestMatcherAssert implements AssertDelegateTarget { private final StaticApplicationContext context;