diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java index cc660abc7a..3d4ba2aa45 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * {@link ServletContextInitializer} to register {@link ExposableServletEndpoint servlet @@ -47,10 +48,17 @@ public class ServletEndpointRegistrar implements ServletContextInitializer { public ServletEndpointRegistrar(String basePath, Collection servletEndpoints) { Assert.notNull(servletEndpoints, "ServletEndpoints must not be null"); - this.basePath = (basePath != null) ? basePath : ""; + this.basePath = cleanBasePath(basePath); this.servletEndpoints = servletEndpoints; } + private static String cleanBasePath(String basePath) { + if (StringUtils.hasText(basePath) && basePath.endsWith("/")) { + return basePath.substring(0, basePath.length() - 1); + } + return (basePath != null) ? basePath : ""; + } + @Override public void onStartup(ServletContext servletContext) throws ServletException { this.servletEndpoints diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrarTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrarTests.java index 542f435bc2..96cfc705ab 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrarTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrarTests.java @@ -16,7 +16,6 @@ package org.springframework.boot.actuate.endpoint.web; -import java.io.IOException; import java.util.Collections; import javax.servlet.GenericServlet; @@ -47,6 +46,7 @@ import static org.mockito.Mockito.verify; * Tests for {@link ServletEndpointRegistrar}. * * @author Phillip Webb + * @author Stephane Nicoll */ public class ServletEndpointRegistrarTests { @@ -77,29 +77,38 @@ public class ServletEndpointRegistrarTests { } @Test - public void onStartupShouldRegisterServlets() throws Exception { - ExposableServletEndpoint endpoint = mockEndpoint( - new EndpointServlet(TestServlet.class)); - ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(null, - Collections.singleton(endpoint)); - registrar.onStartup(this.servletContext); - verify(this.servletContext).addServlet(eq("test-actuator-endpoint"), - this.servlet.capture()); - assertThat(this.servlet.getValue()).isInstanceOf(TestServlet.class); - verify(this.dynamic).addMapping("/test/*"); + public void onStartupShouldRegisterServlets() throws ServletException { + assertBasePath(null, "/test/*"); + } + + @Test + public void onStartupWhenHasBasePathShouldIncludeBasePath() throws ServletException { + assertBasePath("/actuator", "/actuator/test/*"); + } + + @Test + public void onStartupWhenHasEmptyBasePathShouldPrefixWithSlash() + throws ServletException { + assertBasePath("", "/test/*"); } @Test - public void onStartupWhenHasBasePathShouldIncludeBasePath() throws Exception { + public void onStartupWhenHasRootBasePathShouldNotAddDuplicateSlash() + throws ServletException { + assertBasePath("/", "/test/*"); + } + + private void assertBasePath(String basePath, String expectedMapping) + throws ServletException { ExposableServletEndpoint endpoint = mockEndpoint( new EndpointServlet(TestServlet.class)); - ServletEndpointRegistrar registrar = new ServletEndpointRegistrar("/actuator", + ServletEndpointRegistrar registrar = new ServletEndpointRegistrar(basePath, Collections.singleton(endpoint)); registrar.onStartup(this.servletContext); verify(this.servletContext).addServlet(eq("test-actuator-endpoint"), this.servlet.capture()); assertThat(this.servlet.getValue()).isInstanceOf(TestServlet.class); - verify(this.dynamic).addMapping("/actuator/test/*"); + verify(this.dynamic).addMapping(expectedMapping); } @Test @@ -124,8 +133,7 @@ public class ServletEndpointRegistrarTests { public static class TestServlet extends GenericServlet { @Override - public void service(ServletRequest req, ServletResponse res) - throws ServletException, IOException { + public void service(ServletRequest req, ServletResponse res) { } }