Skip to content

Commit

Permalink
Honour endpoint.enabled:false for nested paths
Browse files Browse the repository at this point in the history
Previously, only invocations of /metricName/ would honour the enabled
property and return a not found (404) response. For endpoints which
support nested paths, access to /metricName/foo would ignore the enabled
flag and return an OK (200) response. Furthermore, there was a comment
in EndpointMvcAdapter that suggested that an endpoint shouldn’t be
called when it is disabled, however this was not the case.

This commit updates EndpointWebMvcAutoConfiguration and
JolokiaAutoConfiguration to only register their MvcEndpoint beans if
the underlying endpoint is enabled. This means that an
EndpointMvcAdapter should not be called if its delegate is disabled,
making the comment described above accurate.

The check for the delegate being enabled has been retained so as not to
rely upon the auto-configurations’ behaviour. The methods which handle
nested paths (MetricsMvcEndpoint.value() and
EnvironmentMvcEndpoint.value()) have been updated to add the same check
for the enablement of their delegate.

Fixes spring-projectsgh-2767
  • Loading branch information
wilkinsona authored and bsodzik committed May 23, 2015
1 parent 37ca094 commit 4c838c6
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
Expand Down Expand Up @@ -51,8 +51,8 @@
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
Expand Down Expand Up @@ -84,6 +84,7 @@
* @author Dave Syer
* @author Phillip Webb
* @author Christian Dupuis
* @author Andy Wilkinson
*/
@Configuration
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
Expand Down Expand Up @@ -155,14 +156,14 @@ public MvcEndpoints mvcEndpoints() {

@Bean
@ConditionalOnBean(EnvironmentEndpoint.class)
@ConditionalOnProperty(prefix = "endpoints.env", name = "enabled", matchIfMissing = true)
@ConditionalOnExpression("${endpoints.env.enabled:${endpoints.enabled:true}}")
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
return new EnvironmentMvcEndpoint(delegate);
}

@Bean
@ConditionalOnBean(HealthEndpoint.class)
@ConditionalOnProperty(prefix = "endpoints.health", name = "enabled", matchIfMissing = true)
@ConditionalOnExpression("${endpoints.health.enabled:${endpoints.enabled:true}}")
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
Security security = this.managementServerProperties.getSecurity();
boolean secure = (security == null || security.isEnabled());
Expand All @@ -176,14 +177,14 @@ public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {

@Bean
@ConditionalOnBean(MetricsEndpoint.class)
@ConditionalOnProperty(prefix = "endpoints.metrics", name = "enabled", matchIfMissing = true)
@ConditionalOnExpression("${endpoints.metrics.enabled:${endpoints.enabled:true}}")
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
return new MetricsMvcEndpoint(delegate);
}

@Bean
@ConditionalOnBean(ShutdownEndpoint.class)
@ConditionalOnProperty(prefix = "endpoints.shutdown", name = "enabled", matchIfMissing = true)
@ConditionalOnExpression("${endpoints.shutdown.enabled:false}")
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
return new ShutdownMvcEndpoint(delegate);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2015 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.
Expand All @@ -25,8 +25,8 @@
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -39,8 +39,8 @@
*
* <p>
* This configuration will get automatically enabled as soon as the Jolokia
* {@link AgentServlet} is on the classpath. To disable set
* <code>endpoints.jolokia.enabled: false</code>.
* {@link AgentServlet} is on the classpath. To disable it set
* <code>endpoints.jolokia.enabled: false</code> or <code>endpoints.enabled: false</code>.
*
* <p>
* Additional configuration parameters for Jolokia can be provided by specifying
Expand All @@ -50,11 +50,12 @@
*
* @author Christian Dupuis
* @author Dave Syer
* @author Andy Wilkinson
*/
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ AgentServlet.class })
@ConditionalOnProperty(prefix = "endpoints.jolokia", name = "enabled", matchIfMissing = true)
@ConditionalOnExpression("${endpoints.jolokia.enabled:${endpoints.enabled:true}}")
@AutoConfigureBefore(ManagementSecurityAutoConfiguration.class)
@AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)
@EnableConfigurationProperties(JolokiaProperties.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
Expand Down Expand Up @@ -31,9 +31,14 @@
* Adapter class to expose {@link Endpoint}s as {@link MvcEndpoint}s.
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class EndpointMvcAdapter implements MvcEndpoint {

private final ResponseEntity<Map<String, String>> disabledResponse = new ResponseEntity<Map<String, String>>(
Collections.singletonMap("message", "This endpoint is disabled"),
HttpStatus.NOT_FOUND);

private final Endpoint<?> delegate;

/**
Expand All @@ -49,9 +54,9 @@ public EndpointMvcAdapter(Endpoint<?> delegate) {
@ResponseBody
public Object invoke() {
if (!this.delegate.isEnabled()) {
// Shouldn't happen
return new ResponseEntity<Map<String, String>>(Collections.singletonMap(
"message", "This endpoint is disabled"), HttpStatus.NOT_FOUND);
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
// disabled
return this.disabledResponse;
}
return this.delegate.invoke();
}
Expand All @@ -76,4 +81,15 @@ public Class<? extends Endpoint> getEndpointType() {
return this.delegate.getClass();
}

/**
* Returns the response that should be returned when the endpoint is disabled.
*
* @see Endpoint#isEnabled()
* @since 1.2.4
* @return The response to be returned when the endpoint is disabled
*/
protected ResponseEntity<?> getDisabledResponse() {
return this.disabledResponse;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
Expand Down Expand Up @@ -31,6 +31,7 @@
*
* @author Dave Syer
* @author Christian Dupuis
* @author Andy Wilkinson
*/
public class EnvironmentMvcEndpoint extends EndpointMvcAdapter implements
EnvironmentAware {
Expand All @@ -44,6 +45,11 @@ public EnvironmentMvcEndpoint(EnvironmentEndpoint delegate) {
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
@ResponseBody
public Object value(@PathVariable String name) {
if (!getDelegate().isEnabled()) {
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
// disabled
return getDisabledResponse();
}
String result = this.environment.getProperty(name);
if (result == null) {
throw new NoSuchPropertyException("No such property: " + name);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
Expand Down Expand Up @@ -28,6 +28,7 @@
* Adapter to expose {@link MetricsEndpoint} as an {@link MvcEndpoint}.
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class MetricsMvcEndpoint extends EndpointMvcAdapter {

Expand All @@ -41,6 +42,11 @@ public MetricsMvcEndpoint(MetricsEndpoint delegate) {
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
@ResponseBody
public Object value(@PathVariable String name) {
if (!this.delegate.isEnabled()) {
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
// disabled
return getDisabledResponse();
}
Object value = this.delegate.invoke().get(name);
if (value == null) {
throw new NoSuchMetricException("No such metric: " + name);
Expand Down
Loading

0 comments on commit 4c838c6

Please sign in to comment.