diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java index 6b3bbae9c7c..9807927b69f 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java @@ -19,17 +19,28 @@ package org.springframework.boot.actuate.endpoint; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; /** * Abstract base for {@link Endpoint} implementations. + *

+ * {@link Endpoint}s that support other {@link HttpMethod}s than {@link HttpMethod#GET} + * should override {@link #methods()} and provide a list of supported methods. * * @author Phillip Webb + * @author Christian Dupuis */ public abstract class AbstractEndpoint implements Endpoint { private static final MediaType[] NO_MEDIA_TYPES = new MediaType[0]; + protected static final HttpMethod[] NO_HTTP_METHOD = new HttpMethod[0]; + + protected static final HttpMethod[] GET_HTTP_METHOD = new HttpMethod[] { HttpMethod.GET }; + + protected static final HttpMethod[] POST_HTTP_METHOD = new HttpMethod[] { HttpMethod.POST }; + @NotNull @Pattern(regexp = "/[^/]*", message = "Path must start with /") private String path; @@ -64,8 +75,12 @@ public abstract class AbstractEndpoint implements Endpoint { } @Override - public MediaType[] getProduces() { + public MediaType[] produces() { return NO_MEDIA_TYPES; } + @Override + public HttpMethod[] methods() { + return GET_HTTP_METHOD; + } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ActionEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ActionEndpoint.java deleted file mode 100644 index bb4a476f871..00000000000 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ActionEndpoint.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2012-2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.actuate.endpoint; - -/** - * Tagging interface used to indicate that {@link Endpoint} that performs some action. - * Allows mappings to refine the types of request supported. - * - * @author Phillip Webb - */ -public interface ActionEndpoint extends Endpoint { - -} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/BeansEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/BeansEndpoint.java index 281dab2e5e0..81108bb769c 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/BeansEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/BeansEndpoint.java @@ -51,7 +51,7 @@ public class BeansEndpoint extends AbstractEndpoint implements } @Override - public MediaType[] getProduces() { + public MediaType[] produces() { return new MediaType[] { MediaType.APPLICATION_JSON }; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java index 8e6800ddc6e..7fe94e4ecdd 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.endpoint; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; /** @@ -24,6 +25,7 @@ import org.springframework.http.MediaType; * * @author Phillip Webb * @author Dave Syer + * @author Christian Dupuis */ public interface Endpoint { @@ -42,7 +44,12 @@ public interface Endpoint { /** * Returns the {@link MediaType}s that this endpoint produces or {@code null}. */ - MediaType[] getProduces(); + MediaType[] produces(); + + /** + * Returns the {@link HttpMethod}s that this endpoint supports. + */ + HttpMethod[] methods(); /** * Called to invoke the endpoint. diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java index 7b08be8554c..38553b9f3b1 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java @@ -26,15 +26,17 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.HttpMethod; /** - * {@link ActionEndpoint} to shutdown the {@link ApplicationContext}. + * {@link Endpoint} to shutdown the {@link ApplicationContext}. * * @author Dave Syer + * @author Christian Dupuis */ @ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false) public class ShutdownEndpoint extends AbstractEndpoint> implements - ApplicationContextAware, ActionEndpoint> { + ApplicationContextAware { private ConfigurableApplicationContext context; @@ -80,4 +82,9 @@ public class ShutdownEndpoint extends AbstractEndpoint> impl } } + @Override + public HttpMethod[] methods() { + return POST_HTTP_METHOD; + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerAdapter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerAdapter.java index 3b50bdd64ad..fd87e531bcc 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerAdapter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerAdapter.java @@ -150,7 +150,7 @@ public final class EndpointHandlerAdapter implements HandlerAdapter { private List getProducibleMediaTypes(Endpoint endpoint, Class returnValueClass) { - MediaType[] mediaTypes = endpoint.getProduces(); + MediaType[] mediaTypes = endpoint.produces(); if (mediaTypes != null && mediaTypes.length != 0) { return Arrays.asList(mediaTypes); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java index 571349d32fe..9e65bfa9662 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java @@ -25,10 +25,10 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.actuate.endpoint.ActionEndpoint; import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.http.HttpMethod; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerExecutionChain; @@ -37,10 +37,9 @@ import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping; /** * {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getPath()}. - * Standard {@link Endpoint}s are mapped to GET requests, {@link ActionEndpoint}s are - * mapped to POST requests. * * @author Phillip Webb + * @author Christian Dupuis * @see EndpointHandlerAdapter */ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements @@ -94,8 +93,9 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements if (handler != null) { Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler) .getHandler() : handler); - String method = (endpoint instanceof ActionEndpoint ? "POST" : "GET"); - if (request.getMethod().equals(method)) { + HttpMethod method = HttpMethod.valueOf(request.getMethod()); + if (endpoint instanceof Endpoint + && supportsMethod(((Endpoint) endpoint).methods(), method)) { return endpoint; } } @@ -131,4 +131,16 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements public List> getEndpoints() { return Collections.unmodifiableList(this.endpoints); } + + private boolean supportsMethod(HttpMethod[] supportedMethods, + HttpMethod requestedMethod) { + Assert.notNull(supportedMethods, "SupportMethods must not be null"); + Assert.notNull(supportedMethods, "RequestedMethod must not be null"); + for (HttpMethod supportedMethod : supportedMethods) { + if (supportedMethod.equals(requestedMethod)) { + return true; + } + } + return false; + } }