diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMapping.java index 1d007859ca..342bb22505 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMapping.java @@ -17,8 +17,10 @@ package org.springframework.boot.actuate.endpoint.web.reactive; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -92,6 +94,10 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi private RequestMappingInfo withEndpointMappedPatterns( ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) { Set patterns = mapping.getPatternsCondition().getPatterns(); + if (patterns.isEmpty()) { + patterns = new HashSet( + Arrays.asList(getPathPatternParser().parse(""))); + } PathPattern[] endpointMappedPatterns = patterns.stream() .map((pattern) -> getEndpointMappedPattern(endpoint, pattern)) .toArray(PathPattern[]::new); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMapping.java index 57490c901e..a8a169b0a6 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMapping.java @@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.web.servlet; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -93,6 +94,9 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi private RequestMappingInfo withEndpointMappedPatterns( ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) { Set patterns = mapping.getPatternsCondition().getPatterns(); + if (patterns.isEmpty()) { + patterns = new HashSet<>(Collections.singletonList("")); + } String[] endpointMappedPatterns = patterns.stream() .map((pattern) -> getEndpointMappedPattern(endpoint, pattern)) .toArray(String[]::new); diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingTests.java index 555155dab9..c789cb0b63 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/reactive/ControllerEndpointHandlerMappingTests.java @@ -78,6 +78,16 @@ public class ControllerEndpointHandlerMappingTests { assertThat(getHandler(mapping, HttpMethod.GET, "/second")).isNull(); } + @Test + public void mappingWithNoPath() throws Exception { + ExposableControllerEndpoint pathless = pathlessEndpoint(); + ControllerEndpointHandlerMapping mapping = createMapping("actuator", pathless); + assertThat(getHandler(mapping, HttpMethod.GET, "/actuator/pathless")) + .isEqualTo(handlerOf(pathless.getController(), "get")); + assertThat(getHandler(mapping, HttpMethod.GET, "/pathless")).isNull(); + assertThat(getHandler(mapping, HttpMethod.GET, "/")).isNull(); + } + @Test public void mappingNarrowedToMethod() throws Exception { ExposableControllerEndpoint first = firstEndpoint(); @@ -118,6 +128,10 @@ public class ControllerEndpointHandlerMappingTests { return mockEndpoint("second", new SecondTestMvcEndpoint()); } + private ExposableControllerEndpoint pathlessEndpoint() { + return mockEndpoint("pathless", new PathlessControllerEndpoint()); + } + private ExposableControllerEndpoint mockEndpoint(String id, Object controller) { ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class); given(endpoint.getId()).willReturn(id); @@ -146,4 +160,14 @@ public class ControllerEndpointHandlerMappingTests { } + @ControllerEndpoint(id = "pathless") + private static class PathlessControllerEndpoint { + + @GetMapping + public String get() { + return "test"; + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingTests.java index 7b18f684e4..acdc57b70b 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMappingTests.java @@ -84,6 +84,16 @@ public class ControllerEndpointHandlerMappingTests { mapping.getHandler(request("POST", "/actuator/first")); } + @Test + public void mappingWithNoPath() throws Exception { + ExposableControllerEndpoint pathless = pathlessEndpoint(); + ControllerEndpointHandlerMapping mapping = createMapping("actuator", pathless); + assertThat(mapping.getHandler(request("GET", "/actuator/pathless")).getHandler()) + .isEqualTo(handlerOf(pathless.getController(), "get")); + assertThat(mapping.getHandler(request("GET", "/pathless"))).isNull(); + assertThat(mapping.getHandler(request("GET", "/"))).isNull(); + } + private ControllerEndpointHandlerMapping createMapping(String prefix, ExposableControllerEndpoint... endpoints) { ControllerEndpointHandlerMapping mapping = new ControllerEndpointHandlerMapping( @@ -110,6 +120,10 @@ public class ControllerEndpointHandlerMappingTests { return mockEndpoint("second", new SecondTestMvcEndpoint()); } + private ExposableControllerEndpoint pathlessEndpoint() { + return mockEndpoint("pathless", new PathlessControllerEndpoint()); + } + private ExposableControllerEndpoint mockEndpoint(String id, Object controller) { ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class); given(endpoint.getId()).willReturn(id); @@ -138,4 +152,14 @@ public class ControllerEndpointHandlerMappingTests { } + @ControllerEndpoint(id = "pathless") + private static class PathlessControllerEndpoint { + + @GetMapping + public String get() { + return "test"; + } + + } + }