From df5dfbf4be36b7c3f96f2c332db8bc2aa82dcbc7 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sat, 13 Oct 2018 23:20:16 -0700 Subject: [PATCH] Support mixed case endpoint includes/excludes Update `ExposeExcludePropertyEndpointFilter` so that mixed case endpoint IDs are supported. Prior to this commit it was not easy for an endpoint to be missed by the filter due to the formatting of the property value. See gh-14773 --- .../ExposeExcludePropertyEndpointFilter.java | 13 ++++++++++++- .../ExposeExcludePropertyEndpointFilterTests.java | 6 ++++++ .../boot/actuate/endpoint/EndpointId.java | 10 ++++++++++ .../boot/actuate/endpoint/EndpointIdTests.java | 6 ++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilter.java index c435e84d94..0504d89031 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilter.java @@ -21,11 +21,13 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; import org.springframework.boot.actuate.endpoint.EndpointFilter; +import org.springframework.boot.actuate.endpoint.EndpointId; import org.springframework.boot.actuate.endpoint.ExposableEndpoint; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; @@ -74,10 +76,19 @@ public class ExposeExcludePropertyEndpointFilter> } private Set bind(Binder binder, String name) { - return asSet(binder.bind(name, Bindable.listOf(String.class)) + return asSet(binder.bind(name, Bindable.listOf(String.class)).map(this::cleanup) .orElseGet(ArrayList::new)); } + private List cleanup(List values) { + return values.stream().map(this::cleanup).collect(Collectors.toList()); + } + + private String cleanup(String value) { + return "*".equals(value) ? "*" + : EndpointId.fromPropertyValue(value).toLowerCaseString(); + } + private Set asSet(Collection items) { if (items == null) { return Collections.emptySet(); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilterTests.java index e386c989a2..98baeb8c59 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilterTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/ExposeExcludePropertyEndpointFilterTests.java @@ -147,6 +147,12 @@ public class ExposeExcludePropertyEndpointFilterTests { assertThat(match(EndpointId.of("buz"))).isFalse(); } + @Test + public void matchWhenMixedCaseShouldMatch() { + setupFilter("foo-bar", ""); + assertThat(match(EndpointId.of("fooBar"))).isTrue(); + } + private void setupFilter(String include, String exclude) { MockEnvironment environment = new MockEnvironment(); environment.setProperty("foo.include", include); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointId.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointId.java index 246ff3c29d..bb52d75bf9 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointId.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointId.java @@ -87,4 +87,14 @@ public final class EndpointId { return new EndpointId(value); } + /** + * Factory method to create a new {@link EndpointId} from a property value. Is more + * lenient that {@link #of(String)} to allow for common "relaxed" property variants. + * @param value the property value to convert + * @return an {@link EndpointId} instance + */ + public static EndpointId fromPropertyValue(String value) { + return new EndpointId(value.replace("-", "")); + } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EndpointIdTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EndpointIdTests.java index 9c11e8f2ef..7f085211b0 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EndpointIdTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EndpointIdTests.java @@ -93,4 +93,10 @@ public class EndpointIdTests { assertThat(EndpointId.of("fooBar").toString()).isEqualTo("fooBar"); } + @Test + public void fromPropertyValueStripsDashes() { + EndpointId fromPropertyValue = EndpointId.fromPropertyValue("foo-bar"); + assertThat(fromPropertyValue).isEqualTo(EndpointId.of("fooBar")); + } + }