From 389422938136c880b638140c9a79341a68c79148 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 27 Sep 2017 11:45:50 +0200 Subject: [PATCH] Fix status handling of /application/env/{propertyName} This commit makes sure to return a 404 status if the env endpoint is invoked with a property that does not exist in the environment. Closes gh-10179 --- .../EnvironmentEndpointAutoConfiguration.java | 11 +++++ .../env/EnvironmentWebEndpointExtension.java | 49 +++++++++++++++++++ ...nvironmentEndpointWebIntegrationTests.java | 17 +++++++ 3 files changed, 77 insertions(+) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentWebEndpointExtension.java diff --git a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java index cb7aaae0a2..c460d01349 100644 --- a/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java +++ b/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java @@ -18,7 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.env; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.env.EnvironmentEndpoint; +import org.springframework.boot.actuate.env.EnvironmentWebEndpointExtension; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -55,4 +57,13 @@ public class EnvironmentEndpointAutoConfiguration { return endpoint; } + @Bean + @ConditionalOnMissingBean + @ConditionalOnEnabledEndpoint + @ConditionalOnBean(EnvironmentEndpoint.class) + public EnvironmentWebEndpointExtension environmentWebEndpointExtension( + EnvironmentEndpoint environmentEndpoint) { + return new EnvironmentWebEndpointExtension(environmentEndpoint); + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentWebEndpointExtension.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentWebEndpointExtension.java new file mode 100644 index 0000000000..704e4f5651 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentWebEndpointExtension.java @@ -0,0 +1,49 @@ +/* + * 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.env; + +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.boot.actuate.endpoint.annotation.Selector; +import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse; +import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointExtension; +import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentEntryDescriptor; + +/** + * {@link WebEndpointExtension} for the {@link EnvironmentEndpoint}. + * + * @author Stephane Nicoll + * @since 2.0.0 + */ +@WebEndpointExtension(endpoint = EnvironmentEndpoint.class) +public class EnvironmentWebEndpointExtension { + + private final EnvironmentEndpoint delegate; + + public EnvironmentWebEndpointExtension(EnvironmentEndpoint delegate) { + this.delegate = delegate; + } + + @ReadOperation + public WebEndpointResponse environmentEntry( + @Selector String toMatch) { + EnvironmentEntryDescriptor descriptor = this.delegate.environmentEntry(toMatch); + int status = descriptor.getProperty() != null ? WebEndpointResponse.STATUS_OK + : WebEndpointResponse.STATUS_NOT_FOUND; + return new WebEndpointResponse<>(descriptor, status); + } + +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointWebIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointWebIntegrationTests.java index cbc4eddc26..b6afa66b31 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointWebIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointWebIntegrationTests.java @@ -96,6 +96,17 @@ public class EnvironmentEndpointWebIntegrationTests { .jsonPath(forPropertyEntry("placeholder")).isEqualTo("******"); } + @Test + public void nestedPathForUnknownKeyShouldReturn404AndBody() throws Exception { + client.get().uri("/application/env/this.does.not.exist").exchange().expectStatus() + .isNotFound() + .expectBody() + .jsonPath("property").doesNotExist() + .jsonPath("propertySources[?(@.name=='test')]").exists() + .jsonPath("propertySources[?(@.name=='systemProperties')]").exists() + .jsonPath("propertySources[?(@.name=='systemEnvironment')]").exists(); + } + @Test public void nestedPathMatchedByRegexWhenPlaceholderCannotBeResolvedShouldReturnUnresolvedProperty() throws Exception { @@ -140,6 +151,12 @@ public class EnvironmentEndpointWebIntegrationTests { return new EnvironmentEndpoint(environment); } + @Bean + public EnvironmentWebEndpointExtension webEndpointExtension( + EnvironmentEndpoint endpoint) { + return new EnvironmentWebEndpointExtension(endpoint); + } + } }