mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Add a property to disable the /actuator
discovery page
Closes gh-24693
This commit is contained in:
parent
3610fe50b7
commit
c05cb21ab7
@ -51,6 +51,8 @@ public class WebEndpointProperties {
|
||||
*/
|
||||
private final Map<String, String> pathMapping = new LinkedHashMap<>();
|
||||
|
||||
private final Discovery discovery = new Discovery();
|
||||
|
||||
public Exposure getExposure() {
|
||||
return this.exposure;
|
||||
}
|
||||
@ -75,6 +77,10 @@ public class WebEndpointProperties {
|
||||
return this.pathMapping;
|
||||
}
|
||||
|
||||
public Discovery getDiscovery() {
|
||||
return this.discovery;
|
||||
}
|
||||
|
||||
public static class Exposure {
|
||||
|
||||
/**
|
||||
@ -105,4 +111,21 @@ public class WebEndpointProperties {
|
||||
|
||||
}
|
||||
|
||||
public static class Discovery {
|
||||
|
||||
/**
|
||||
* Whether the discovery page is enabled.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -71,15 +71,15 @@ class JerseyWebEndpointManagementContextConfiguration {
|
||||
ServletEndpointsSupplier servletEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
|
||||
WebEndpointProperties webEndpointProperties) {
|
||||
String basePath = webEndpointProperties.getBasePath();
|
||||
boolean shouldRegisterLinks = shouldRegisterLinksMapping(environment, basePath);
|
||||
shouldRegisterLinksMapping(environment, basePath);
|
||||
boolean shouldRegisterLinks = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
|
||||
return new JerseyWebEndpointsResourcesRegistrar(resourceConfig.getIfAvailable(), webEndpointsSupplier,
|
||||
servletEndpointsSupplier, endpointMediaTypes, basePath, shouldRegisterLinks);
|
||||
}
|
||||
|
||||
private boolean shouldRegisterLinksMapping(Environment environment, String basePath) {
|
||||
return StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT);
|
||||
private boolean shouldRegisterLinksMapping(WebEndpointProperties properties, Environment environment,
|
||||
String basePath) {
|
||||
return properties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,12 +75,13 @@ public class WebFluxEndpointManagementContextConfiguration {
|
||||
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
||||
return new WebFluxEndpointHandlerMapping(endpointMapping, endpoints, endpointMediaTypes,
|
||||
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
|
||||
shouldRegisterLinksMapping(environment, basePath));
|
||||
shouldRegisterLinksMapping(webEndpointProperties, environment, basePath));
|
||||
}
|
||||
|
||||
private boolean shouldRegisterLinksMapping(Environment environment, String basePath) {
|
||||
return StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT);
|
||||
private boolean shouldRegisterLinksMapping(WebEndpointProperties properties, Environment environment,
|
||||
String basePath) {
|
||||
return properties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -74,13 +74,18 @@ public class WebMvcEndpointManagementContextConfiguration {
|
||||
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
||||
String basePath = webEndpointProperties.getBasePath();
|
||||
EndpointMapping endpointMapping = new EndpointMapping(basePath);
|
||||
boolean shouldRegisterLinksMapping = StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT);
|
||||
boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
|
||||
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
|
||||
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
|
||||
shouldRegisterLinksMapping);
|
||||
}
|
||||
|
||||
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment,
|
||||
String basePath) {
|
||||
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|
||||
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ControllerEndpointHandlerMapping controllerEndpointHandlerMapping(
|
||||
|
@ -50,29 +50,44 @@ class JerseyEndpointIntegrationTests {
|
||||
testJerseyEndpoints(new Class<?>[] { EndpointsConfiguration.class, ResourceConfigConfiguration.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksPageIsNotAvailableWhenDisabled() {
|
||||
getContextRunner(new Class[] { EndpointsConfiguration.class, ResourceConfigConfiguration.class })
|
||||
.withPropertyValues("management.endpoints.web.discovery.enabled:false").run((context) -> {
|
||||
int port = context
|
||||
.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isNotFound();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void actuatorEndpointsWhenUserProvidedResourceConfigBeanNotAvailable() {
|
||||
testJerseyEndpoints(new Class<?>[] { EndpointsConfiguration.class });
|
||||
}
|
||||
|
||||
protected void testJerseyEndpoints(Class<?>[] userConfigurations) {
|
||||
getContextRunner(userConfigurations).run((context) -> {
|
||||
int port = context.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").doesNotExist().jsonPath("_links.controller")
|
||||
.doesNotExist();
|
||||
});
|
||||
}
|
||||
|
||||
WebApplicationContextRunner getContextRunner(Class<?>[] userConfigurations) {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(DispatcherServlet.class);
|
||||
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||
return new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||
.withClassLoader(classLoader)
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(userConfigurations)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*", "server.port:0").run((context) -> {
|
||||
int port = context
|
||||
.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").doesNotExist().jsonPath("_links.controller")
|
||||
.doesNotExist();
|
||||
});
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*", "server.port:0");
|
||||
}
|
||||
|
||||
@ControllerEndpoint(id = "controller")
|
||||
|
@ -43,21 +43,29 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
*/
|
||||
class WebFluxEndpointIntegrationTests {
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(EndpointsConfiguration.class);
|
||||
|
||||
@Test
|
||||
void linksAreProvidedToAllEndpointTypes() throws Exception {
|
||||
new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(EndpointsConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*").run((context) -> {
|
||||
WebTestClient client = createWebTestClient(context);
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").isNotEmpty().jsonPath("_links.controller")
|
||||
.isNotEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include:*").run((context) -> {
|
||||
WebTestClient client = createWebTestClient(context);
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").isNotEmpty().jsonPath("_links.controller")
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksPageIsNotAvailableWhenDisabled() throws Exception {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.discovery.enabled=false").run((context) -> {
|
||||
WebTestClient client = createWebTestClient(context);
|
||||
client.get().uri("/actuator").exchange().expectStatus().isNotFound();
|
||||
});
|
||||
}
|
||||
|
||||
private WebTestClient createWebTestClient(ApplicationContext context) {
|
||||
|
@ -119,6 +119,15 @@ class WebMvcEndpointIntegrationTests {
|
||||
both(hasKey("beans")).and(hasKey("servlet")).and(hasKey("restcontroller")).and(hasKey("controller"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksPageIsNotAvailableWhenDisabled() throws Exception {
|
||||
this.context = new AnnotationConfigServletWebApplicationContext();
|
||||
this.context.register(DefaultConfiguration.class, EndpointsConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.discovery.enabled=false").applyTo(this.context);
|
||||
MockMvc mockMvc = doCreateMockMvc();
|
||||
mockMvc.perform(get("/actuator").accept("*/*")).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
private MockMvc createSecureMockMvc() {
|
||||
return doCreateMockMvc(springSecurity());
|
||||
}
|
||||
|
@ -425,6 +425,17 @@ NOTE: The prefix `management.endpoint.<name>` is used to uniquely identify the e
|
||||
A "`discovery page`" is added with links to all the endpoints.
|
||||
The "`discovery page`" is available on `/actuator` by default.
|
||||
|
||||
To disable the "`discovery page`", add the following property to your application properties:
|
||||
|
||||
[source,yaml,indent=0,configprops,configblocks]
|
||||
----
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
discovery:
|
||||
enabled: false
|
||||
----
|
||||
|
||||
When a custom management context path is configured, the "`discovery page`" automatically moves from `/actuator` to the root of the management context.
|
||||
For example, if the management context path is `/management`, then the discovery page is available from `/management`.
|
||||
When the management context path is set to `/`, the discovery page is disabled to prevent the possibility of a clash with other mappings.
|
||||
|
Loading…
Reference in New Issue
Block a user