All MVC endpoint paths to be separately customized from the id
This change applies only to "standard" MVC endpoints (not the extended
ones like /env and /jolokia which already have this feature). Allows
users to supply an endpoints.{name}.path.
Fixes gh-2790
This commit is contained in:
@@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
public class EndpointMvcAdapter implements MvcEndpoint {
|
public class EndpointMvcAdapter implements MvcEndpoint {
|
||||||
|
|
||||||
private final Endpoint<?> delegate;
|
private final Endpoint<?> delegate;
|
||||||
|
private String path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link EndpointMvcAdapter}.
|
* Create a new {@link EndpointMvcAdapter}.
|
||||||
@@ -58,7 +59,17 @@ public class EndpointMvcAdapter implements MvcEndpoint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return "/" + this.delegate.getId();
|
return this.path != null ? this.path : "/" + this.delegate.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
while (path.endsWith("/")) {
|
||||||
|
path = path.substring(0, path.length() - 1);
|
||||||
|
}
|
||||||
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
|||||||
|
|
||||||
private Health cached;
|
private Health cached;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
public HealthMvcEndpoint(HealthEndpoint delegate) {
|
public HealthMvcEndpoint(HealthEndpoint delegate) {
|
||||||
this(delegate, true);
|
this(delegate, true);
|
||||||
}
|
}
|
||||||
@@ -125,8 +127,9 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
|||||||
public Object invoke(Principal principal) {
|
public Object invoke(Principal principal) {
|
||||||
if (!this.delegate.isEnabled()) {
|
if (!this.delegate.isEnabled()) {
|
||||||
// Shouldn't happen because the request mapping should not be registered
|
// Shouldn't happen because the request mapping should not be registered
|
||||||
return new ResponseEntity<Map<String, String>>(Collections.singletonMap(
|
return new ResponseEntity<Map<String, String>>(
|
||||||
"message", "This endpoint is disabled"), HttpStatus.NOT_FOUND);
|
Collections.singletonMap("message", "This endpoint is disabled"),
|
||||||
|
HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
Health health = getHealth(principal);
|
Health health = getHealth(principal);
|
||||||
HttpStatus status = getStatus(health);
|
HttpStatus status = getStatus(health);
|
||||||
@@ -174,8 +177,8 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSecure(Principal principal) {
|
private boolean isSecure(Principal principal) {
|
||||||
return (principal != null && !principal.getClass().getName()
|
return (principal != null
|
||||||
.contains("Anonymous"));
|
&& !principal.getClass().getName().contains("Anonymous"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isUnrestricted() {
|
private boolean isUnrestricted() {
|
||||||
@@ -185,7 +188,17 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return "/" + this.delegate.getId();
|
return this.path != null ? this.path : "/" + this.delegate.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
if (!path.startsWith("/")) {
|
||||||
|
path = "/" + path;
|
||||||
|
}
|
||||||
|
while (path.endsWith("/")) {
|
||||||
|
path = path.substring(0, path.length() - 1);
|
||||||
|
}
|
||||||
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -58,11 +58,18 @@ public class MvcEndpoints implements ApplicationContextAware, InitializingBean {
|
|||||||
this.endpoints.addAll(existing);
|
this.endpoints.addAll(existing);
|
||||||
this.customTypes = findEndpointClasses(existing);
|
this.customTypes = findEndpointClasses(existing);
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
Collection<Endpoint> delegates = BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
Collection<Endpoint> delegates = BeanFactoryUtils
|
||||||
this.applicationContext, Endpoint.class).values();
|
.beansOfTypeIncludingAncestors(this.applicationContext, Endpoint.class)
|
||||||
|
.values();
|
||||||
for (Endpoint<?> endpoint : delegates) {
|
for (Endpoint<?> endpoint : delegates) {
|
||||||
if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {
|
if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {
|
||||||
this.endpoints.add(new EndpointMvcAdapter(endpoint));
|
EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);
|
||||||
|
String path = this.applicationContext.getEnvironment()
|
||||||
|
.getProperty("endpoints." + endpoint.getId() + ".path");
|
||||||
|
if (path != null) {
|
||||||
|
adapter.setPath(path);
|
||||||
|
}
|
||||||
|
this.endpoints.add(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.mvc;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||||
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
import org.springframework.context.support.StaticApplicationContext;
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -62,6 +63,19 @@ public class MvcEndpointsTests {
|
|||||||
assertEquals(1, this.endpoints.getEndpoints().size());
|
assertEquals(1, this.endpoints.getEndpoints().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void changesPath() throws Exception {
|
||||||
|
EnvironmentTestUtils.addEnvironment(this.context,
|
||||||
|
"endpoints.test.path=/foo/bar/");
|
||||||
|
this.context.getDefaultListableBeanFactory().registerSingleton("endpoint",
|
||||||
|
new TestEndpoint());
|
||||||
|
this.endpoints.setApplicationContext(this.context);
|
||||||
|
this.endpoints.afterPropertiesSet();
|
||||||
|
assertEquals(1, this.endpoints.getEndpoints().size());
|
||||||
|
assertEquals("/foo/bar",
|
||||||
|
this.endpoints.getEndpoints().iterator().next().getPath());
|
||||||
|
}
|
||||||
|
|
||||||
protected static class TestEndpoint extends AbstractEndpoint<String> {
|
protected static class TestEndpoint extends AbstractEndpoint<String> {
|
||||||
|
|
||||||
public TestEndpoint() {
|
public TestEndpoint() {
|
||||||
|
|||||||
@@ -166,8 +166,6 @@ For example, the following will disable _all_ endpoints except for `info`:
|
|||||||
endpoints.info.enabled=true
|
endpoints.info.enabled=true
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[production-ready-endpoint-hypermedia]]
|
[[production-ready-endpoint-hypermedia]]
|
||||||
=== Hypermedia for actuator MVC endpoints
|
=== Hypermedia for actuator MVC endpoints
|
||||||
If http://projects.spring.io/spring-hateoas[Spring HATEOAS] is on the classpath (e.g.
|
If http://projects.spring.io/spring-hateoas[Spring HATEOAS] is on the classpath (e.g.
|
||||||
@@ -502,7 +500,7 @@ you should carefully consider which endpoints you enable. See
|
|||||||
|
|
||||||
|
|
||||||
[[production-ready-customizing-management-server-context-path]]
|
[[production-ready-customizing-management-server-context-path]]
|
||||||
=== Customizing the management server context path
|
=== Customizing the management endpoint paths
|
||||||
Sometimes it is useful to group all management endpoints under a single path. For example,
|
Sometimes it is useful to group all management endpoints under a single path. For example,
|
||||||
your application might already use `/info` for another purpose. You can use the
|
your application might already use `/info` for another purpose. You can use the
|
||||||
`management.context-path` property to set a prefix for your management endpoint:
|
`management.context-path` property to set a prefix for your management endpoint:
|
||||||
@@ -515,6 +513,23 @@ your application might already use `/info` for another purpose. You can use the
|
|||||||
The `application.properties` example above will change the endpoint from `/{id}` to
|
The `application.properties` example above will change the endpoint from `/{id}` to
|
||||||
`/manage/{id}` (e.g. `/manage/info`).
|
`/manage/{id}` (e.g. `/manage/info`).
|
||||||
|
|
||||||
|
You can also change the "id" of an endpoint (using
|
||||||
|
`endpoints.{name}.id`) which then changes the default resource path
|
||||||
|
for the MVC endpoint. Legal endpoint ids are composed only of
|
||||||
|
alphanumeric characters (because they can be exposed in a number of
|
||||||
|
places, including JMX object names, where special characters are
|
||||||
|
forbidden). The MVC path can be changed separately by configuring
|
||||||
|
`endpoints.{name}.path`, and there is no validation on those values
|
||||||
|
(so you can use anything that is legel in a URL path). For example, to
|
||||||
|
change the location of the `/health` endpoint to `/ping/me` you can
|
||||||
|
set `endpoints.health.path=/ping/me`.
|
||||||
|
|
||||||
|
TIP: If you provide a custom `MvcEndpoint` remember to include a
|
||||||
|
settable `path` property, and default it to `/{id}` if you want your
|
||||||
|
code to behave like the standard MVC endpoints. (Take a look at the
|
||||||
|
`HealthMvcEndpoint` to see how you might do that.) If your custom
|
||||||
|
endpoint is an `Endpoint` (not an `MvcEndpoint`) then Spring Boot will
|
||||||
|
take care of the path for you.
|
||||||
|
|
||||||
|
|
||||||
[[production-ready-customizing-management-server-port]]
|
[[production-ready-customizing-management-server-port]]
|
||||||
|
|||||||
Reference in New Issue
Block a user