Allow management endpoints to express what http methods they support
Previously a management endpoint was either GET or POST. That requirement seems limited.
This commit is contained in:
parent
845aeecbad
commit
405c9d5593
|
|
@ -19,17 +19,28 @@ package org.springframework.boot.actuate.endpoint;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base for {@link Endpoint} implementations.
|
* Abstract base for {@link Endpoint} implementations.
|
||||||
|
* <p>
|
||||||
|
* {@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 Phillip Webb
|
||||||
|
* @author Christian Dupuis
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||||
|
|
||||||
private static final MediaType[] NO_MEDIA_TYPES = new MediaType[0];
|
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
|
@NotNull
|
||||||
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
@Pattern(regexp = "/[^/]*", message = "Path must start with /")
|
||||||
private String path;
|
private String path;
|
||||||
|
|
@ -64,8 +75,12 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaType[] getProduces() {
|
public MediaType[] produces() {
|
||||||
return NO_MEDIA_TYPES;
|
return NO_MEDIA_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpMethod[] methods() {
|
||||||
|
return GET_HTTP_METHOD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<T> extends Endpoint<T> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -51,7 +51,7 @@ public class BeansEndpoint extends AbstractEndpoint<String> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaType[] getProduces() {
|
public MediaType[] produces() {
|
||||||
return new MediaType[] { MediaType.APPLICATION_JSON };
|
return new MediaType[] { MediaType.APPLICATION_JSON };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.endpoint;
|
package org.springframework.boot.actuate.endpoint;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -24,6 +25,7 @@ import org.springframework.http.MediaType;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Christian Dupuis
|
||||||
*/
|
*/
|
||||||
public interface Endpoint<T> {
|
public interface Endpoint<T> {
|
||||||
|
|
||||||
|
|
@ -42,7 +44,12 @@ public interface Endpoint<T> {
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MediaType}s that this endpoint produces or {@code null}.
|
* 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.
|
* Called to invoke the endpoint.
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,17 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
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 Dave Syer
|
||||||
|
* @author Christian Dupuis
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false)
|
@ConfigurationProperties(name = "endpoints.shutdown", ignoreUnknownFields = false)
|
||||||
public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> implements
|
||||||
ApplicationContextAware, ActionEndpoint<Map<String, Object>> {
|
ApplicationContextAware {
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
|
@ -80,4 +82,9 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>> impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpMethod[] methods() {
|
||||||
|
return POST_HTTP_METHOD;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ public final class EndpointHandlerAdapter implements HandlerAdapter {
|
||||||
|
|
||||||
private List<MediaType> getProducibleMediaTypes(Endpoint<?> endpoint,
|
private List<MediaType> getProducibleMediaTypes(Endpoint<?> endpoint,
|
||||||
Class<?> returnValueClass) {
|
Class<?> returnValueClass) {
|
||||||
MediaType[] mediaTypes = endpoint.getProduces();
|
MediaType[] mediaTypes = endpoint.produces();
|
||||||
if (mediaTypes != null && mediaTypes.length != 0) {
|
if (mediaTypes != null && mediaTypes.length != 0) {
|
||||||
return Arrays.asList(mediaTypes);
|
return Arrays.asList(mediaTypes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.boot.actuate.endpoint.ActionEndpoint;
|
|
||||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
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()}.
|
* {@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 Phillip Webb
|
||||||
|
* @author Christian Dupuis
|
||||||
* @see EndpointHandlerAdapter
|
* @see EndpointHandlerAdapter
|
||||||
*/
|
*/
|
||||||
public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||||
|
|
@ -94,8 +93,9 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler)
|
Object endpoint = (handler instanceof HandlerExecutionChain ? ((HandlerExecutionChain) handler)
|
||||||
.getHandler() : handler);
|
.getHandler() : handler);
|
||||||
String method = (endpoint instanceof ActionEndpoint<?> ? "POST" : "GET");
|
HttpMethod method = HttpMethod.valueOf(request.getMethod());
|
||||||
if (request.getMethod().equals(method)) {
|
if (endpoint instanceof Endpoint
|
||||||
|
&& supportsMethod(((Endpoint<?>) endpoint).methods(), method)) {
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,4 +131,16 @@ public class EndpointHandlerMapping extends AbstractUrlHandlerMapping implements
|
||||||
public List<Endpoint<?>> getEndpoints() {
|
public List<Endpoint<?>> getEndpoints() {
|
||||||
return Collections.unmodifiableList(this.endpoints);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue