mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Simplify the Actuator's hypermedia support
This commit replaces the Acuator's support for hypermedia with a single endpoint that returns HAL-formatted links to all of the available endpoints. This is done without requiring Spring HATEOAS to be on the classpath in a similar manner to the existing CloudFoundry discovery endpoint. Closes gh-9901
This commit is contained in:
parent
4a61e45644
commit
9f75da9a8f
@ -1,331 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ActuatorMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalBrowserMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HypermediaDisabled;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ManagementServletContext;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.TypeUtils;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
/**
|
||||
* Configuration for hypermedia in HTTP endpoints.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ManagementContextConfiguration
|
||||
@ConditionalOnClass(Link.class)
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnBean(HttpMessageConverters.class)
|
||||
@ConditionalOnEnabledEndpoint("actuator")
|
||||
@EnableConfigurationProperties({ ResourceProperties.class,
|
||||
ManagementServerProperties.class })
|
||||
public class EndpointWebMvcHypermediaManagementContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public ManagementServletContext managementServletContext(
|
||||
final ManagementServerProperties properties) {
|
||||
return properties::getContextPath;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HalJsonMvcEndpoint halJsonMvcEndpoint(
|
||||
ManagementServletContext managementServletContext,
|
||||
ResourceProperties resources, ResourceLoader resourceLoader) {
|
||||
if (HalBrowserMvcEndpoint.getHalBrowserLocation(resourceLoader) != null) {
|
||||
return new HalBrowserMvcEndpoint(managementServletContext);
|
||||
}
|
||||
return new HalJsonMvcEndpoint(managementServletContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller advice that adds links to the actuator endpoint's path.
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public static class ActuatorEndpointLinksAdvice
|
||||
implements ResponseBodyAdvice<Object> {
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints endpoints;
|
||||
|
||||
@Autowired(required = false)
|
||||
private HalJsonMvcEndpoint halJsonMvcEndpoint;
|
||||
|
||||
@Autowired
|
||||
private ManagementServerProperties management;
|
||||
|
||||
private LinksEnhancer linksEnhancer;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.linksEnhancer = new LinksEnhancer(this.management.getContextPath(),
|
||||
this.endpoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType,
|
||||
Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
returnType.increaseNestingLevel();
|
||||
Type nestedType = returnType.getNestedGenericParameterType();
|
||||
returnType.decreaseNestingLevel();
|
||||
return ResourceSupport.class.isAssignableFrom(returnType.getParameterType())
|
||||
|| TypeUtils.isAssignable(ResourceSupport.class, nestedType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
beforeBodyWrite(body, (ServletServerHttpRequest) request);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
private void beforeBodyWrite(Object body, ServletServerHttpRequest request) {
|
||||
Object pattern = request.getServletRequest()
|
||||
.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
if (pattern != null && body instanceof ResourceSupport) {
|
||||
beforeBodyWrite(pattern.toString(), (ResourceSupport) body);
|
||||
}
|
||||
}
|
||||
|
||||
private void beforeBodyWrite(String path, ResourceSupport body) {
|
||||
if (isActuatorEndpointPath(path)) {
|
||||
this.linksEnhancer.addEndpointLinks(body,
|
||||
this.halJsonMvcEndpoint.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isActuatorEndpointPath(String path) {
|
||||
if (this.halJsonMvcEndpoint != null) {
|
||||
String toMatch = this.management.getContextPath()
|
||||
+ this.halJsonMvcEndpoint.getPath();
|
||||
return toMatch.equals(path) || (toMatch + "/").equals(path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller advice that adds links to the existing Actuator endpoints. By default
|
||||
* all the top-level resources are enhanced with a "self" link. Those resources that
|
||||
* could not be enhanced (e.g. "/env/{name}") because their values are "primitive" are
|
||||
* ignored.
|
||||
*/
|
||||
@ConditionalOnProperty(prefix = "endpoints.hypermedia", name = "enabled", matchIfMissing = false)
|
||||
@ControllerAdvice(assignableTypes = MvcEndpoint.class)
|
||||
static class MvcEndpointAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
private final List<RequestMappingHandlerAdapter> handlerAdapters;
|
||||
|
||||
private final Map<MediaType, HttpMessageConverter<?>> converterCache = new ConcurrentHashMap<>();
|
||||
|
||||
MvcEndpointAdvice(List<RequestMappingHandlerAdapter> handlerAdapters) {
|
||||
this.handlerAdapters = handlerAdapters;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void configureHttpMessageConverters() {
|
||||
for (RequestMappingHandlerAdapter handlerAdapter : this.handlerAdapters) {
|
||||
for (HttpMessageConverter<?> messageConverter : handlerAdapter
|
||||
.getMessageConverters()) {
|
||||
configureHttpMessageConverter(messageConverter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configureHttpMessageConverter(
|
||||
HttpMessageConverter<?> messageConverter) {
|
||||
if (messageConverter instanceof TypeConstrainedMappingJackson2HttpMessageConverter) {
|
||||
List<MediaType> supportedMediaTypes = new ArrayList<>(
|
||||
messageConverter.getSupportedMediaTypes());
|
||||
supportedMediaTypes.add(ActuatorMediaTypes.APPLICATION_ACTUATOR_V2_JSON);
|
||||
((AbstractHttpMessageConverter<?>) messageConverter)
|
||||
.setSupportedMediaTypes(supportedMediaTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType,
|
||||
Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
Class<?> controllerType = returnType.getDeclaringClass();
|
||||
return !HalJsonMvcEndpoint.class.isAssignableFrom(controllerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (request instanceof ServletServerHttpRequest) {
|
||||
return beforeBodyWrite(body, returnType, selectedContentType,
|
||||
selectedConverterType, (ServletServerHttpRequest) request,
|
||||
response);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
private Object beforeBodyWrite(Object body, MethodParameter returnType,
|
||||
MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServletServerHttpRequest request, ServerHttpResponse response) {
|
||||
if (body == null || body instanceof Resource) {
|
||||
// Assume it already was handled or it already has its links
|
||||
return body;
|
||||
}
|
||||
if (body instanceof Collection || body.getClass().isArray()) {
|
||||
// We can't add links to a collection without wrapping it
|
||||
return body;
|
||||
}
|
||||
HttpMessageConverter<Object> converter = findConverter(selectedConverterType,
|
||||
selectedContentType);
|
||||
if (converter == null || isHypermediaDisabled(returnType)) {
|
||||
// Not a resource that can be enhanced with a link
|
||||
return body;
|
||||
}
|
||||
String path = getPath(request);
|
||||
try {
|
||||
converter.write(new EndpointResource(body, path), selectedContentType,
|
||||
response);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HttpMessageNotWritableException("Cannot write response", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private HttpMessageConverter<Object> findConverter(
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
MediaType mediaType) {
|
||||
HttpMessageConverter<Object> cached = (HttpMessageConverter<Object>) this.converterCache
|
||||
.get(mediaType);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
for (RequestMappingHandlerAdapter handlerAdapter : this.handlerAdapters) {
|
||||
for (HttpMessageConverter<?> converter : handlerAdapter
|
||||
.getMessageConverters()) {
|
||||
if (selectedConverterType.isAssignableFrom(converter.getClass())
|
||||
&& converter.canWrite(EndpointResource.class, mediaType)) {
|
||||
this.converterCache.put(mediaType, converter);
|
||||
return (HttpMessageConverter<Object>) converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isHypermediaDisabled(MethodParameter returnType) {
|
||||
return AnnotationUtils.findAnnotation(returnType.getMethod(),
|
||||
HypermediaDisabled.class) != null
|
||||
|| AnnotationUtils.findAnnotation(
|
||||
returnType.getMethod().getDeclaringClass(),
|
||||
HypermediaDisabled.class) != null;
|
||||
}
|
||||
|
||||
private String getPath(ServletServerHttpRequest request) {
|
||||
String path = (String) request.getServletRequest()
|
||||
.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
return (path == null ? "" : path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JsonInclude(content = Include.NON_NULL)
|
||||
@JacksonXmlRootElement(localName = "resource")
|
||||
private static class EndpointResource extends ResourceSupport {
|
||||
|
||||
private Object content;
|
||||
|
||||
private Map<String, Object> embedded;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
EndpointResource(Object content, String path) {
|
||||
this.content = content instanceof Map ? null : content;
|
||||
this.embedded = (Map<String, Object>) (this.content == null ? content : null);
|
||||
add(linkTo(Object.class).slash(path).withSelfRel());
|
||||
}
|
||||
|
||||
@JsonUnwrapped
|
||||
public Object getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, Object> getEmbedded() {
|
||||
return this.embedded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,7 @@ import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@ -379,7 +380,7 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||
if (endpointHandlerMapping == null) {
|
||||
// Maybe there are actually no endpoints (e.g. management.port=-1)
|
||||
endpointHandlerMapping = new EndpointHandlerMapping(
|
||||
Collections.<MvcEndpoint>emptySet());
|
||||
Collections.<NamedMvcEndpoint>emptySet());
|
||||
}
|
||||
return endpointHandlerMapping;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
||||
@ -50,10 +49,7 @@ class CloudFoundryEndpointHandlerMapping
|
||||
HealthMvcEndpoint healthMvcEndpoint = null;
|
||||
while (iterator.hasNext()) {
|
||||
NamedMvcEndpoint endpoint = iterator.next();
|
||||
if (endpoint instanceof HalJsonMvcEndpoint) {
|
||||
iterator.remove();
|
||||
}
|
||||
else if (endpoint instanceof HealthMvcEndpoint) {
|
||||
if (endpoint instanceof HealthMvcEndpoint) {
|
||||
iterator.remove();
|
||||
healthMvcEndpoint = (HealthMvcEndpoint) endpoint;
|
||||
}
|
||||
|
@ -17,9 +17,17 @@
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
@ -63,4 +71,67 @@ public class EndpointHandlerMapping extends AbstractEndpointHandlerMapping<MvcEn
|
||||
super(endpoints, corsConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
detectHandlerMethods(new EndpointLinksMvcEndpoint(
|
||||
getEndpoints().stream().filter(NamedMvcEndpoint.class::isInstance)
|
||||
.map(NamedMvcEndpoint.class::cast).collect(Collectors.toSet())));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MvcEndpoint} to provide HAL-formatted links to all the
|
||||
* {@link NamedMvcEndpoint named endpoints}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
private static final class EndpointLinksMvcEndpoint extends AbstractMvcEndpoint {
|
||||
|
||||
private final Set<NamedMvcEndpoint> endpoints;
|
||||
|
||||
private EndpointLinksMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
||||
super("", false);
|
||||
this.endpoints = endpoints;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ActuatorGetMapping
|
||||
public Map<String, Map<String, Link>> links(HttpServletRequest request) {
|
||||
Map<String, Link> links = new LinkedHashMap<>();
|
||||
String url = request.getRequestURL().toString();
|
||||
if (url.endsWith("/")) {
|
||||
url = url.substring(0, url.length() - 1);
|
||||
}
|
||||
links.put("self", Link.withHref(url));
|
||||
for (NamedMvcEndpoint endpoint : this.endpoints) {
|
||||
links.put(endpoint.getName(),
|
||||
Link.withHref(url + "/" + endpoint.getName()));
|
||||
}
|
||||
return Collections.singletonMap("_links", links);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Details for a link in the HAL response.
|
||||
*/
|
||||
static final class Link {
|
||||
|
||||
private final String href;
|
||||
|
||||
private Link(String href) {
|
||||
this.href = href;
|
||||
}
|
||||
|
||||
public String getHref() {
|
||||
return this.href;
|
||||
}
|
||||
|
||||
static Link withHref(Object href) {
|
||||
return new Link(href.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ public class EnvironmentMvcEndpoint extends EndpointMvcAdapter
|
||||
|
||||
@ActuatorGetMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
@HypermediaDisabled
|
||||
public Object value(@PathVariable String name) {
|
||||
if (!getDelegate().isEnabled()) {
|
||||
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
|
||||
|
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.resource.ResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.ResourceTransformerChain;
|
||||
import org.springframework.web.servlet.resource.TransformedResource;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* {@link MvcEndpoint} to expose a HAL browser.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class HalBrowserMvcEndpoint extends HalJsonMvcEndpoint
|
||||
implements ResourceLoaderAware {
|
||||
|
||||
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private static HalBrowserLocation[] HAL_BROWSER_RESOURCE_LOCATIONS = {
|
||||
new HalBrowserLocation("classpath:/META-INF/spring-data-rest/hal-browser/",
|
||||
"index.html"),
|
||||
new HalBrowserLocation(
|
||||
"classpath:/META-INF/resources/webjars/hal-browser/3325375/",
|
||||
"browser.html") };
|
||||
|
||||
private HalBrowserLocation location;
|
||||
|
||||
public HalBrowserMvcEndpoint(ManagementServletContext managementServletContext) {
|
||||
super(managementServletContext);
|
||||
}
|
||||
|
||||
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String browse(HttpServletRequest request) {
|
||||
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder
|
||||
.fromRequest(request);
|
||||
String uriString = builder.build().toUriString();
|
||||
|
||||
return "redirect:" + uriString + (uriString.endsWith("/") ? "" : "/")
|
||||
+ this.location.getHtmlFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.location = getHalBrowserLocation(resourceLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// Make sure the root path is not cached so the browser comes back for the JSON
|
||||
// and add a transformer to set the initial link
|
||||
if (this.location != null) {
|
||||
String start = getManagementServletContext().getContextPath() + getPath();
|
||||
registry.addResourceHandler(start + "/", start + "/**")
|
||||
.addResourceLocations(this.location.getResourceLocation())
|
||||
.setCachePeriod(0).resourceChain(true)
|
||||
.addTransformer(new InitialUrlTransformer());
|
||||
}
|
||||
}
|
||||
|
||||
public static HalBrowserLocation getHalBrowserLocation(
|
||||
ResourceLoader resourceLoader) {
|
||||
for (HalBrowserLocation candidate : HAL_BROWSER_RESOURCE_LOCATIONS) {
|
||||
try {
|
||||
Resource resource = resourceLoader.getResource(candidate.toString());
|
||||
if (resource != null && resource.exists()) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* HAL Browser properties.
|
||||
*/
|
||||
public static class HalBrowserLocation {
|
||||
|
||||
private final String resourceLocation;
|
||||
|
||||
private final String htmlFile;
|
||||
|
||||
public HalBrowserLocation(String resourceLocation, String html) {
|
||||
this.resourceLocation = resourceLocation;
|
||||
this.htmlFile = html;
|
||||
}
|
||||
|
||||
public String getResourceLocation() {
|
||||
return this.resourceLocation;
|
||||
}
|
||||
|
||||
public String getHtmlFile() {
|
||||
return this.htmlFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.resourceLocation + this.htmlFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ResourceTransformer} to change the initial link location.
|
||||
*/
|
||||
private class InitialUrlTransformer implements ResourceTransformer {
|
||||
|
||||
@Override
|
||||
public Resource transform(HttpServletRequest request, Resource resource,
|
||||
ResourceTransformerChain transformerChain) throws IOException {
|
||||
resource = transformerChain.transform(request, resource);
|
||||
if (resource.getFilename().equalsIgnoreCase(
|
||||
HalBrowserMvcEndpoint.this.location.getHtmlFile())) {
|
||||
return replaceInitialLink(request, resource);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
private Resource replaceInitialLink(HttpServletRequest request, Resource resource)
|
||||
throws IOException {
|
||||
byte[] bytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
|
||||
String content = new String(bytes, DEFAULT_CHARSET);
|
||||
List<String> pathSegments = new ArrayList<>(ServletUriComponentsBuilder
|
||||
.fromRequest(request).build().getPathSegments());
|
||||
pathSegments.remove(pathSegments.size() - 1);
|
||||
String initial = "/"
|
||||
+ StringUtils.collectionToDelimitedString(pathSegments, "/");
|
||||
content = content.replace("entryPoint: '/'", "entryPoint: '" + initial + "'");
|
||||
return new TransformedResource(resource, content.getBytes(DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* {@link MvcEndpoint} to expose HAL-formatted JSON.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.actuator")
|
||||
public class HalJsonMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||
|
||||
private final ManagementServletContext managementServletContext;
|
||||
|
||||
public HalJsonMvcEndpoint(ManagementServletContext managementServletContext) {
|
||||
super("actuator", getDefaultPath(managementServletContext), false);
|
||||
this.managementServletContext = managementServletContext;
|
||||
}
|
||||
|
||||
private static String getDefaultPath(
|
||||
ManagementServletContext managementServletContext) {
|
||||
if (StringUtils.hasText(managementServletContext.getContextPath())) {
|
||||
return "";
|
||||
}
|
||||
return "/application";
|
||||
}
|
||||
|
||||
@ActuatorGetMapping
|
||||
@ResponseBody
|
||||
public ResourceSupport links() {
|
||||
return new ResourceSupport();
|
||||
}
|
||||
|
||||
protected final ManagementServletContext getManagementServletContext() {
|
||||
return this.managementServletContext;
|
||||
}
|
||||
|
||||
}
|
@ -55,7 +55,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.heapdump")
|
||||
@HypermediaDisabled
|
||||
public class HeapdumpMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||
|
||||
private final long timeout;
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.mvc;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* Annotation to indicate that an {@link MvcEndpoint} class or {@link RequestMapping}
|
||||
* method shouldn't generate a hypermedia response.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface HypermediaDisabled {
|
||||
|
||||
}
|
@ -44,7 +44,6 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.jolokia", ignoreUnknownFields = false)
|
||||
@HypermediaDisabled
|
||||
public class JolokiaMvcEndpoint extends AbstractNamedMvcEndpoint implements
|
||||
InitializingBean, ApplicationContextAware, ServletContextAware, DisposableBean {
|
||||
|
||||
|
@ -47,7 +47,6 @@ public class LoggersMvcEndpoint extends EndpointMvcAdapter {
|
||||
|
||||
@ActuatorGetMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
@HypermediaDisabled
|
||||
public Object get(@PathVariable String name) {
|
||||
if (!this.delegate.isEnabled()) {
|
||||
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
|
||||
@ -60,7 +59,6 @@ public class LoggersMvcEndpoint extends EndpointMvcAdapter {
|
||||
|
||||
@ActuatorPostMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
@HypermediaDisabled
|
||||
public Object set(@PathVariable String name,
|
||||
@RequestBody Map<String, String> configuration) {
|
||||
if (!this.delegate.isEnabled()) {
|
||||
|
@ -44,7 +44,6 @@ public class MetricsMvcEndpoint extends EndpointMvcAdapter {
|
||||
|
||||
@ActuatorGetMapping("/{name:.*}")
|
||||
@ResponseBody
|
||||
@HypermediaDisabled
|
||||
public Object value(@PathVariable String name) {
|
||||
if (!this.delegate.isEnabled()) {
|
||||
// Shouldn't happen - MVC endpoint shouldn't be registered when delegate's
|
||||
|
@ -47,12 +47,6 @@
|
||||
"vcap_services"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "endpoints.hypermedia.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable hypermedia support for endpoints.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "endpoints.info.path",
|
||||
"type": "java.lang.String",
|
||||
|
@ -19,5 +19,4 @@ org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration,\
|
||||
org.springframework.boot.actuate.cloudfoundry.CloudFoundryActuatorAutoConfiguration
|
||||
|
||||
org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\
|
||||
org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration
|
||||
|
@ -45,7 +45,6 @@ import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMappingCustomizer;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
|
||||
@ -437,7 +436,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
this.applicationContext.refresh();
|
||||
// /health, /metrics, /loggers, /env, /actuator, /heapdump, /auditevents
|
||||
// (/shutdown is disabled by default)
|
||||
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class)).hasSize(7);
|
||||
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class)).hasSize(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -500,18 +499,6 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorEndpointEnabledIndividually() {
|
||||
this.applicationContext.register(RootConfig.class, BaseConfiguration.class,
|
||||
EndpointWebMvcAutoConfiguration.class);
|
||||
TestPropertyValues
|
||||
.of("endpoints.enabled:false", "endpoints.actuator.enabled:true")
|
||||
.applyTo(this.applicationContext);
|
||||
this.applicationContext.refresh();
|
||||
assertThat(this.applicationContext.getBeansOfType(HalJsonMvcEndpoint.class))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void managementSpecificSslUsingDifferentPort() throws Exception {
|
||||
TestPropertyValues
|
||||
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.autoconfigure;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ManagementServletContext;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.hateoas.hal.DefaultCurieProvider;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link EndpointWebMvcHypermediaManagementContextConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class EndpointWebMvcHypermediaManagementContextConfigurationTests {
|
||||
|
||||
private AnnotationConfigWebApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setRequestAttributes() {
|
||||
RequestContextHolder.setRequestAttributes(
|
||||
new ServletRequestAttributes(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@After
|
||||
public void resetRequestAttributes() {
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
}
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicConfiguration() {
|
||||
load();
|
||||
assertThat(this.context.getBeansOfType(ManagementServletContext.class))
|
||||
.hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(HalJsonMvcEndpoint.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(DefaultCurieProvider.class)).isEmpty();
|
||||
}
|
||||
|
||||
private void load(String... properties) {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
TestPropertyValues.of(properties).applyTo(this.context);
|
||||
this.context.register(TestConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
EndpointWebMvcHypermediaManagementContextConfiguration.class);
|
||||
this.context.refresh();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({ ManagementServerProperties.class,
|
||||
ServerProperties.class })
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public MvcEndpoints mvcEndpoints() {
|
||||
return new MvcEndpoints();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -25,8 +25,8 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpointSecurityInterceptor;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
||||
import org.springframework.boot.actuate.servlet.MockServletWebServerFactory;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
@ -138,7 +138,7 @@ public class JolokiaAutoConfigurationTests {
|
||||
|
||||
@Bean
|
||||
public EndpointHandlerMapping endpointHandlerMapping(
|
||||
Collection<? extends MvcEndpoint> endpoints) {
|
||||
Collection<NamedMvcEndpoint> endpoints) {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints);
|
||||
mapping.setSecurityInterceptor(new MvcEndpointSecurityInterceptor(false,
|
||||
Collections.<String>emptyList()));
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.autoconfigure;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Minimal configuration required to run the Actuator with hypermedia.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
HypermediaAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, AuditAutoConfiguration.class })
|
||||
public @interface MinimalActuatorHypermediaApplication {
|
||||
|
||||
}
|
@ -38,7 +38,6 @@ import org.springframework.boot.actuate.endpoint.TraceEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.JolokiaMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.LogFileMvcEndpoint;
|
||||
@ -82,7 +81,7 @@ public class MvcEndpointPathConfigurationTests {
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Object[] parameters() {
|
||||
return new Object[] { new Object[] { "actuator", HalJsonMvcEndpoint.class },
|
||||
return new Object[] {
|
||||
new Object[] { "auditevents", AuditEventsMvcEndpoint.class },
|
||||
new Object[] { "autoconfig", AutoConfigurationReportEndpoint.class },
|
||||
new Object[] { "beans", BeansEndpoint.class },
|
||||
|
@ -24,7 +24,6 @@ import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointHandlerMappingTests;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
@ -54,13 +53,6 @@ public class CloudFoundryEndpointHandlerMappingTests
|
||||
assertThat(handlerMapping.getPath(testMvcEndpoint)).isEqualTo("/a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotRegisterHalJsonMvcEndpoint() throws Exception {
|
||||
CloudFoundryEndpointHandlerMapping handlerMapping = new CloudFoundryEndpointHandlerMapping(
|
||||
Collections.singleton(new TestHalJsonMvcEndpoint()), null, null);
|
||||
assertThat(handlerMapping.getEndpoints()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersCloudFoundryDiscoveryEndpoint() throws Exception {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
@ -114,14 +106,6 @@ public class CloudFoundryEndpointHandlerMappingTests
|
||||
|
||||
}
|
||||
|
||||
private static class TestHalJsonMvcEndpoint extends HalJsonMvcEndpoint {
|
||||
|
||||
TestHalJsonMvcEndpoint() {
|
||||
super(() -> "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestHealthMvcEndpoint extends HealthMvcEndpoint {
|
||||
|
||||
TestHealthMvcEndpoint(HealthEndpoint delegate) {
|
||||
|
@ -89,6 +89,7 @@ public class RequestMappingEndpointTests {
|
||||
assertThat(map.get("bean")).isEqualTo("scopedTarget.mapping");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void beanMethodMappings() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
@ -99,14 +100,21 @@ public class RequestMappingEndpointTests {
|
||||
context.getDefaultListableBeanFactory().registerSingleton("mapping", mapping);
|
||||
this.endpoint.setApplicationContext(context);
|
||||
Map<String, Object> result = this.endpoint.invoke();
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.keySet().iterator().next().contains("/dump")).isTrue();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> handler = (Map<String, Object>) result.values().iterator()
|
||||
.next();
|
||||
assertThat(handler.containsKey("method")).isTrue();
|
||||
assertThat(result).hasSize(2);
|
||||
assertThat(result.keySet())
|
||||
.filteredOn((key) -> key.contains("/dump || /dump.json"))
|
||||
.hasOnlyOneElementSatisfying((key) -> {
|
||||
assertThat((Map<String, Object>) result.get(key))
|
||||
.containsOnlyKeys("bean", "method");
|
||||
});
|
||||
assertThat(result.keySet()).filteredOn((key) -> key.contains(" || /.json"))
|
||||
.hasOnlyOneElementSatisfying((key) -> {
|
||||
assertThat((Map<String, Object>) result.get(key))
|
||||
.containsOnlyKeys("bean", "method");
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void concreteMethodMappings() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
@ -116,12 +124,18 @@ public class RequestMappingEndpointTests {
|
||||
this.endpoint.setMethodMappings(
|
||||
Collections.<AbstractHandlerMethodMapping<?>>singletonList(mapping));
|
||||
Map<String, Object> result = this.endpoint.invoke();
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.keySet().iterator().next().contains("/dump")).isTrue();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> handler = (Map<String, Object>) result.values().iterator()
|
||||
.next();
|
||||
assertThat(handler.containsKey("method")).isTrue();
|
||||
assertThat(result).hasSize(2);
|
||||
assertThat(result.keySet())
|
||||
.filteredOn((key) -> key.contains("/dump || /dump.json"))
|
||||
.hasOnlyOneElementSatisfying((key) -> {
|
||||
assertThat((Map<String, Object>) result.get(key))
|
||||
.containsOnlyKeys("method");
|
||||
});
|
||||
assertThat(result.keySet()).filteredOn((key) -> key.contains(" || /.json"))
|
||||
.hasOnlyOneElementSatisfying((key) -> {
|
||||
assertThat((Map<String, Object>) result.get(key))
|
||||
.containsOnlyKeys("method");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
@ -62,6 +62,8 @@ public class EndpointHandlerMappingTests extends AbstractEndpointHandlerMappingT
|
||||
assertThat(mapping.getHandler(request("GET", "/b")).getHandler())
|
||||
.isEqualTo(new HandlerMethod(endpointB, this.method));
|
||||
assertThat(mapping.getHandler(request("GET", "/c"))).isNull();
|
||||
assertThat((((HandlerMethod) mapping.getHandler(request("GET", "/")).getHandler())
|
||||
.getMethod().getName())).isEqualTo("links");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,7 +79,12 @@ public class EndpointHandlerMappingTests extends AbstractEndpointHandlerMappingT
|
||||
.getHandler()).isEqualTo(new HandlerMethod(endpointA, this.method));
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a/b"))
|
||||
.getHandler()).isEqualTo(new HandlerMethod(endpointB, this.method));
|
||||
assertThat(mapping.getHandler(request("GET", "/a"))).isNull();
|
||||
assertThat(
|
||||
(((HandlerMethod) mapping.getHandler(request("GET", "/a")).getHandler())
|
||||
.getMethod().getName())).isEqualTo("links");
|
||||
assertThat(
|
||||
(((HandlerMethod) mapping.getHandler(request("GET", "/a/")).getHandler())
|
||||
.getMethod().getName())).isEqualTo("links");
|
||||
}
|
||||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint}'s support for producing text/html
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = "endpoints.actuator.path=/actuator")
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointBrowserPathIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithTrailingSlashIsRedirectedToBrowserHtml() throws Exception {
|
||||
this.mockMvc.perform(get("/application/actuator/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string(HttpHeaders.LOCATION,
|
||||
"http://localhost/application/actuator/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithoutTrailingSlashIsRedirectedToBrowserHtml() throws Exception {
|
||||
this.mockMvc.perform(get("/application/actuator").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound()).andExpect(header().string("location",
|
||||
"http://localhost/application/actuator/browser.html"));
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@Configuration
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint}
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = "management.security.enabled=false")
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointDisabledIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksOnActuator() throws Exception {
|
||||
this.mockMvc.perform(get("/application").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(header().doesNotExist("cache-control"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void browserRedirect() throws Exception {
|
||||
this.mockMvc.perform(get("/application/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string(HttpHeaders.LOCATION,
|
||||
"http://localhost/application/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsDoNotHaveLinks() throws Exception {
|
||||
for (MvcEndpoint endpoint : this.mvcEndpoints.getEndpoints()) {
|
||||
String path = endpoint.getPath();
|
||||
if ("".equals(path) || endpoint instanceof HeapdumpMvcEndpoint) {
|
||||
continue;
|
||||
}
|
||||
path = "/application" + (path.length() > 0 ? path : "/");
|
||||
MockHttpServletRequestBuilder requestBuilder = get(path);
|
||||
if (endpoint instanceof AuditEventsMvcEndpoint) {
|
||||
requestBuilder.param("after", "2016-01-01T12:00:00+00:00");
|
||||
}
|
||||
this.mockMvc.perform(requestBuilder.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links").doesNotExist());
|
||||
}
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@Configuration
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringBootHypermediaApplication.class,
|
||||
"--endpoints.hypermedia.enabled=false");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.mvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint} when endpoints are disabled.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = "endpoints.enabled=false")
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointEndpointsDisabledIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void links() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void browser() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trace() throws Exception {
|
||||
this.mockMvc.perform(get("/trace").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void envValue() throws Exception {
|
||||
this.mockMvc.perform(get("/env/user.home").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsAllDisabled() throws Exception {
|
||||
assertThat(this.mvcEndpoints.getEndpoints()).isEmpty();
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@Configuration
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.mvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint} when a custom management context
|
||||
* path has been configured.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = { "management.contextPath:/admin",
|
||||
"management.security.enabled=false" })
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointManagementContextPathIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorHomeJson() throws Exception {
|
||||
this.mockMvc.perform(get("/admin").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorHomeWithTrailingSlashJson() throws Exception {
|
||||
this.mockMvc.perform(get("/admin/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorHomeHtml() throws Exception {
|
||||
this.mockMvc.perform(get("/admin/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound()).andExpect(header().string(
|
||||
HttpHeaders.LOCATION, "http://localhost/admin/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorBrowserHtml() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/admin/browser.html").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("entryPoint: '/admin'")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trace() throws Exception {
|
||||
this.mockMvc.perform(get("/admin/trace").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").doesNotExist())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsAllListed() throws Exception {
|
||||
for (MvcEndpoint endpoint : this.mvcEndpoints.getEndpoints()) {
|
||||
String path = endpoint.getPath();
|
||||
if ("/actuator".equals(path)) {
|
||||
continue;
|
||||
}
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
path = path.length() > 0 ? path : "self";
|
||||
this.mockMvc.perform(get("/admin").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.%s.href", path)
|
||||
.value("http://localhost/admin" + endpoint.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@RestController
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
@RequestMapping("")
|
||||
public ResourceSupport home() {
|
||||
ResourceSupport resource = new ResourceSupport();
|
||||
resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/")
|
||||
.withSelfRel());
|
||||
return resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint} when a custom server context path
|
||||
* has been configured.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
|
||||
"server.servlet.contextPath=/spring" })
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointServerContextPathIntegrationTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void linksAddedToHomePage() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorBrowserRedirect() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||
assertThat(entity.getHeaders().getLocation()).isEqualTo(URI.create(
|
||||
"http://localhost:" + this.port + "/spring/application/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorBrowserEntryPoint() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/browser.html",
|
||||
HttpMethod.GET, new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("entryPoint: '/spring/application'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorLinks() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorLinksWithTrailingSlash() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@RestController
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
@RequestMapping("")
|
||||
public ResourceSupport home() {
|
||||
ResourceSupport resource = new ResourceSupport();
|
||||
resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/")
|
||||
.withSelfRel());
|
||||
return resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint} when a custom server port has been
|
||||
* configured.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
|
||||
"management.port=0" })
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointServerPortIntegrationTests {
|
||||
|
||||
@Value("${local.management.port}")
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void links() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/application", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
assertThat(entity.getBody()).contains(":" + this.port);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithTrailingSlash() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
assertThat(entity.getBody()).contains(":" + this.port);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void browserRedirect() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||
assertThat(entity.getHeaders().getLocation()).isEqualTo(URI
|
||||
.create("http://localhost:" + this.port + "/application/browser.html"));
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@RestController
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
@RequestMapping("")
|
||||
public ResourceSupport home() {
|
||||
ResourceSupport resource = new ResourceSupport();
|
||||
resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/")
|
||||
.withSelfRel());
|
||||
return resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint} when a custom server servlet path
|
||||
* has been configured.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
|
||||
"server.servlet.path=/spring" })
|
||||
@DirtiesContext
|
||||
public class HalBrowserMvcEndpointServerServletPathIntegrationTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void linksAddedToHomePage() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorBrowserRedirect() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||
assertThat(entity.getHeaders().getLocation()).isEqualTo(URI.create(
|
||||
"http://localhost:" + this.port + "/spring/application/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorBrowserEntryPoint() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/browser.html",
|
||||
HttpMethod.GET, new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("entryPoint: '/spring/application'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorLinks() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actuatorLinksWithTrailingSlash() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(
|
||||
"http://localhost:" + this.port + "/spring/application/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(null, headers), String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@RestController
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
@RequestMapping("")
|
||||
public ResourceSupport home() {
|
||||
ResourceSupport resource = new ResourceSupport();
|
||||
resource.add(linkTo(SpringBootHypermediaApplication.class).slash("/")
|
||||
.withSelfRel());
|
||||
return resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.MinimalActuatorHypermediaApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowserMvcEndpoint}
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@DirtiesContext
|
||||
@TestPropertySource(properties = { "endpoints.hypermedia.enabled=true",
|
||||
"management.security.enabled=false" })
|
||||
public class HalBrowserMvcEndpointVanillaIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private MvcEndpoints mvcEndpoints;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void links() throws Exception {
|
||||
this.mockMvc.perform(get("/application").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(header().doesNotExist("cache-control"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithTrailingSlash() throws Exception {
|
||||
this.mockMvc.perform(get("/application/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists())
|
||||
.andExpect(header().doesNotExist("cache-control"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void browser() throws Exception {
|
||||
this.mockMvc.perform(get("/application/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string(HttpHeaders.LOCATION,
|
||||
"http://localhost/application/browser.html"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trace() throws Exception {
|
||||
this.mockMvc.perform(get("/application/trace").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").doesNotExist())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void envValue() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/application/env/user.home")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsAllListed() throws Exception {
|
||||
for (MvcEndpoint endpoint : this.mvcEndpoints.getEndpoints()) {
|
||||
String path = endpoint.getPath();
|
||||
if ("/application".equals(path)) {
|
||||
continue;
|
||||
}
|
||||
path = path.startsWith("/") ? path.substring(1) : path;
|
||||
this.mockMvc.perform(get("/application").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.%s.href", path).exists());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsEachHaveSelf() throws Exception {
|
||||
Set<String> collections = new HashSet<>(Arrays.asList("/trace", "/beans", "/dump",
|
||||
"/heapdump", "/loggers", "/auditevents"));
|
||||
for (MvcEndpoint endpoint : this.mvcEndpoints.getEndpoints()) {
|
||||
String path = endpoint.getPath();
|
||||
if (collections.contains(path)) {
|
||||
continue;
|
||||
}
|
||||
path = "/application" + (path.length() > 0 ? path : "/");
|
||||
this.mockMvc.perform(get(path).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links.self.href")
|
||||
.value("http://localhost/application" + endpoint.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
@MinimalActuatorHypermediaApplication
|
||||
@Configuration
|
||||
public static class SpringBootHypermediaApplication {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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.mvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HalJsonMvcEndpoint}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class HalJsonMvcEndpointTests {
|
||||
|
||||
@Mock
|
||||
ManagementServletContext managementServletContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halJsonEndpointPathWhenManagementContextPathPresent() throws Exception {
|
||||
Mockito.when(this.managementServletContext.getContextPath()).thenReturn("my-app");
|
||||
HalJsonMvcEndpoint endpoint = new HalJsonMvcEndpoint(
|
||||
this.managementServletContext);
|
||||
assertThat(endpoint.getPath()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halJsonEndpointPathWhenManagementContextPathNotPresent()
|
||||
throws Exception {
|
||||
Mockito.when(this.managementServletContext.getContextPath()).thenReturn("");
|
||||
HalJsonMvcEndpoint endpoint = new HalJsonMvcEndpoint(
|
||||
this.managementServletContext);
|
||||
assertThat(endpoint.getPath()).isEqualTo("/application");
|
||||
}
|
||||
}
|
@ -1085,9 +1085,6 @@ content into your application; rather pick only the properties that you need.
|
||||
# ENDPOINTS ({sc-spring-boot-actuator}/endpoint/AbstractEndpoint.{sc-ext}[AbstractEndpoint] subclasses)
|
||||
endpoints.enabled=true # Enable endpoints.
|
||||
endpoints.sensitive= # Default endpoint sensitive setting.
|
||||
endpoints.actuator.enabled=true # Enable the endpoint.
|
||||
endpoints.actuator.path= # Endpoint URL path.
|
||||
endpoints.actuator.sensitive=false # Enable security on the endpoint.
|
||||
endpoints.auditevents.enabled= # Enable the endpoint.
|
||||
endpoints.auditevents.path= # Endpoint path.
|
||||
endpoints.auditevents.sensitive=false # Enable security on the endpoint.
|
||||
@ -1129,7 +1126,6 @@ content into your application; rather pick only the properties that you need.
|
||||
endpoints.heapdump.enabled= # Enable the endpoint.
|
||||
endpoints.heapdump.path= # Endpoint path.
|
||||
endpoints.heapdump.sensitive= # Mark if the endpoint exposes sensitive information.
|
||||
endpoints.hypermedia.enabled=false # Enable hypermedia support for endpoints.
|
||||
endpoints.info.enabled= # Enable the endpoint.
|
||||
endpoints.info.id= # Endpoint identifier.
|
||||
endpoints.info.path= # Endpoint path.
|
||||
|
@ -69,11 +69,6 @@ The following technology agnostic endpoints are available:
|
||||
|===
|
||||
| ID | Description | Sensitive Default
|
||||
|
||||
|`actuator`
|
||||
|Provides a hypermedia-based "`discovery page`" for the other endpoints. Requires Spring
|
||||
HATEOAS to be on the classpath.
|
||||
|true
|
||||
|
||||
|`auditevents`
|
||||
|Exposes audit events information for the current application.
|
||||
|true
|
||||
@ -207,25 +202,14 @@ For example, to mark _all_ endpoints as sensitive except `info`:
|
||||
|
||||
[[production-ready-endpoint-hypermedia]]
|
||||
=== Hypermedia for actuator MVC endpoints
|
||||
If `endpoints.hypermedia.enabled` is set to `true` and
|
||||
http://projects.spring.io/spring-hateoas[Spring HATEOAS] is on the classpath (e.g.
|
||||
through the `spring-boot-starter-hateoas` or if you are using
|
||||
http://projects.spring.io/spring-data-rest[Spring Data REST]) then the HTTP endpoints
|
||||
from the Actuator are enhanced with hypermedia links, and a "`discovery page`" is added
|
||||
with links to all the endpoints. The "`discovery page`" is available on `/application` by
|
||||
default. It is implemented as an endpoint, allowing properties to be used to configure
|
||||
its path (`endpoints.actuator.path`) and whether or not it is enabled
|
||||
(`endpoints.actuator.enabled`).
|
||||
A "`discovery page`" is added with links to all the endpoints. The "`discovery page`" is
|
||||
available on `/application` by default.
|
||||
|
||||
When a custom management context path is configured, the "`discovery page`" will
|
||||
automatically move from `/application` to the root of the management context. For example,
|
||||
if the management context path is `/management` then the discovery page will be available
|
||||
from `/management`.
|
||||
|
||||
If the https://github.com/mikekelly/hal-browser[HAL Browser] is on the classpath
|
||||
via its webjar (`org.webjars:hal-browser`), or via the `spring-data-rest-hal-browser` then
|
||||
an HTML "`discovery page`", in the form of the HAL Browser, is also provided.
|
||||
|
||||
|
||||
|
||||
[[production-ready-endpoint-cors]]
|
||||
|
@ -80,22 +80,6 @@ The following sample applications are provided:
|
||||
| link:spring-boot-sample-hateoas[spring-boot-sample-hateoas]
|
||||
| RESTful API built using Spring Hateoas
|
||||
|
||||
| link:spring-boot-sample-hypermedia[spring-boot-sample-hypermedia]
|
||||
| Demonstrates Actuator's hypermedia support, including HAL Browser
|
||||
|
||||
| link:spring-boot-sample-hypermedia-gson[spring-boot-sample-hypermedia-gson]
|
||||
| Demonstrates Actuator's hypermedia support using GSON in place of Jackson
|
||||
|
||||
| link:spring-boot-sample-hypermedia-jpa[spring-boot-sample-hypermedia-jpa]
|
||||
| Demonstrates Actuator's hypermedia support alongside Spring Data JPA and Spring Data
|
||||
REST
|
||||
|
||||
| link:spring-boot-sample-hypermedia-ui-secure[spring-boot-sample-hypermedia-ui-secure]
|
||||
| Demonstrates Actuator's hypermedia support alongside a static secure web UI
|
||||
|
||||
| link:spring-boot-sample-hypermedia-ui[spring-boot-sample-hypermedia-ui]
|
||||
| Demonstrates Actuator's hypermedia support alongside a static web UI
|
||||
|
||||
| link:spring-boot-sample-integration[spring-boot-sample-integration]
|
||||
| Integration application built using Spring Integration and its Java DSL
|
||||
|
||||
|
@ -46,11 +46,6 @@
|
||||
<module>spring-boot-sample-devtools</module>
|
||||
<module>spring-boot-sample-flyway</module>
|
||||
<module>spring-boot-sample-hateoas</module>
|
||||
<module>spring-boot-sample-hypermedia</module>
|
||||
<module>spring-boot-sample-hypermedia-gson</module>
|
||||
<module>spring-boot-sample-hypermedia-jpa</module>
|
||||
<module>spring-boot-sample-hypermedia-ui</module>
|
||||
<module>spring-boot-sample-hypermedia-ui-secure</module>
|
||||
<module>spring-boot-sample-integration</module>
|
||||
<module>spring-boot-sample-jersey</module>
|
||||
<module>spring-boot-sample-jersey1</module>
|
||||
|
@ -28,10 +28,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
|
@ -1,7 +1,7 @@
|
||||
# logging.file=/tmp/logs/app.log
|
||||
# logging.level.org.springframework.security=DEBUG
|
||||
management.address=127.0.0.1
|
||||
#management.port=8181
|
||||
management.context-path=/
|
||||
|
||||
management.info.build.mode=full
|
||||
|
||||
@ -20,3 +20,5 @@ management.trace.include=REQUEST_HEADERS,RESPONSE_HEADERS,ERRORS,PATH_INFO,\
|
||||
PATH_TRANSLATED,CONTEXT_PATH,USER_PRINCIPAL,PARAMETERS,QUERY_STRING,AUTH_TYPE,\
|
||||
REMOTE_ADDRESS,SESSION_ID,REMOTE_USER
|
||||
|
||||
management.security.enabled = false
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-hypermedia-gson</artifactId>
|
||||
<name>Spring Boot Hypermedia GSON Sample</name>
|
||||
<description>Spring Boot Hypermedia GSON Sample</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia.gson;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleHypermediaGsonApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleHypermediaGsonApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
# management.context-path=/admin
|
||||
management.security.enabled=false
|
||||
|
||||
spring.http.converters.preferred-json-mapper=gson
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia.gson;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = "endpoints.hypermedia.enabled: true")
|
||||
public class SampleHypermediaGsonApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void health() throws Exception {
|
||||
this.mockMvc.perform(get("/application/health").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.links[0].href").value("http://localhost/application/health"))
|
||||
.andExpect(jsonPath("$.content.status").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trace() throws Exception {
|
||||
this.mockMvc.perform(get("/application/trace").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.links").doesNotExist())
|
||||
.andExpect(jsonPath("$").isArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void envValue() throws Exception {
|
||||
this.mockMvc.perform(get("/application/env/user.home").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links").doesNotExist());
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-hypermedia-jpa</artifactId>
|
||||
<name>Spring Boot Hypermedia JPA Sample</name>
|
||||
<description>Spring Boot Hypermedia JPA Sample</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-rest-hal-browser</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia.jpa;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia.jpa;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface BookRepository extends JpaRepository<Book, Long> {
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia.jpa;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleHypermediaJpaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleHypermediaJpaApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
management.context-path=/admin
|
||||
endpoints.docs.curies.enabled=true
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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 sample.hypermedia.jpa;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class SampleHypermediaJpaApplicationIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void links() throws Exception {
|
||||
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void health() throws Exception {
|
||||
this.mockMvc.perform(get("/admin/health").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adminLinks() throws Exception {
|
||||
this.mockMvc.perform(get("/admin").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._links").exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void browser() throws Exception {
|
||||
MvcResult response = this.mockMvc.perform(get("/").accept(MediaType.TEXT_HTML))
|
||||
.andExpect(status().isFound()).andReturn();
|
||||
assertThat(response.getResponse().getHeaders("location").get(0))
|
||||
.isEqualTo("http://localhost/browser/index.html#/");
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-boot-sample-hypermedia-ui-secure</artifactId>
|
||||
<name>Spring Boot Hypermedia UI Secure Sample</name>
|
||||
<description>Spring Boot Hypermedia UI Secure Sample</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia.ui.secure;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleHypermediaUiSecureApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleHypermediaUiSecureApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
</body>
|
||||
</html>
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia.ui.secure;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
|
||||
"endpoints.env.sensitive=false", "foo=bar" })
|
||||
public class SampleHypermediaUiSecureApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void links() {
|
||||
String response = this.restTemplate.getForObject("/application", String.class);
|
||||
assertThat(response).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsecureNestedPath() throws Exception {
|
||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/application/env",
|
||||
String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
ResponseEntity<String> user = this.restTemplate
|
||||
.getForEntity("/application/env/foo", String.class);
|
||||
assertThat(user.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(user.getBody()).contains("{\"foo\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurePath() throws Exception {
|
||||
ResponseEntity<String> entity = this.restTemplate
|
||||
.getForEntity("/application/metrics", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia.ui.secure;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
|
||||
"management.context-path=/admin" })
|
||||
public class SampleHypermediaUiSecureApplicationWithContextPathTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void links() {
|
||||
String response = this.restTemplate.getForObject("/admin", String.class);
|
||||
assertThat(response).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecurePath() throws Exception {
|
||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/admin/metrics",
|
||||
String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-hypermedia-ui</artifactId>
|
||||
<name>Spring Boot Hypermedia UI Sample</name>
|
||||
<description>Spring Boot Hypermedia UI Sample</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia.ui;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleHypermediaUiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleHypermediaUiApplication.class, args);
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
management.security.enabled=false
|
||||
|
||||
management.context-path=/admin
|
@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
</body>
|
||||
</html>
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia.ui;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
|
||||
"management.context-path=" })
|
||||
public class SampleHypermediaUiApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void home() {
|
||||
String response = this.restTemplate.getForObject("/", String.class);
|
||||
assertThat(response).contains("Hello World");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void links() {
|
||||
String response = this.restTemplate.getForObject("/application", String.class);
|
||||
assertThat(response).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithJson() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> response = this.restTemplate.exchange("/application",
|
||||
HttpMethod.GET, new HttpEntity<Void>(headers), String.class);
|
||||
assertThat(response.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void homeWithHtml() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> response = this.restTemplate.exchange("/", HttpMethod.GET,
|
||||
new HttpEntity<Void>(headers), String.class);
|
||||
assertThat(response.getBody()).contains("Hello World");
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-hypermedia</artifactId>
|
||||
<name>Spring Boot Hypermedia Sample</name>
|
||||
<description>Spring Boot Hypermedia Sample</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>hal-browser</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 sample.hypermedia;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleHypermediaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SampleHypermediaApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
# management.context-path=/admin
|
||||
management.security.enabled=false
|
||||
|
||||
endpoints.docs.curies.enabled=true
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2017 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 sample.hypermedia;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class SampleHypermediaApplicationHomePageTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void home() {
|
||||
String response = this.restTemplate.getForObject("/", String.class);
|
||||
assertThat(response).contains("404");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithJson() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> response = this.restTemplate.exchange("/application",
|
||||
HttpMethod.GET, new HttpEntity<Void>(headers), String.class);
|
||||
assertThat(response.getBody()).contains("\"_links\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void halWithHtml() throws Exception {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
||||
ResponseEntity<String> response = this.restTemplate.exchange("/application/",
|
||||
HttpMethod.GET, new HttpEntity<Void>(headers), String.class);
|
||||
assertThat(response.getBody()).contains("HAL Browser");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user