Skip to content

Commit 7e6b560

Browse files
author
miguelgomes
committed
Merge branch 'master' into small-documentation-improve
2 parents 4ea0f82 + 6e2de93 commit 7e6b560

File tree

25 files changed

+330
-108
lines changed

25 files changed

+330
-108
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
1818

19+
import java.util.Set;
20+
import java.util.stream.Collectors;
21+
1922
import org.glassfish.jersey.server.ResourceConfig;
2023

2124
import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
@@ -31,6 +34,7 @@
3134
import org.springframework.context.ApplicationContext;
3235
import org.springframework.context.annotation.Bean;
3336
import org.springframework.context.annotation.Configuration;
37+
import org.springframework.util.StringUtils;
3438
import org.springframework.web.servlet.DispatcherServlet;
3539

3640
/**
@@ -70,14 +74,27 @@ public ServletEndpointRegistrar servletEndpointRegistrar(
7074
ServletEndpointsSupplier servletEndpointsSupplier) {
7175
DispatcherServletPathProvider servletPathProvider = this.context
7276
.getBean(DispatcherServletPathProvider.class);
73-
String servletPath = servletPathProvider.getServletPath();
74-
if (servletPath.equals("/")) {
75-
servletPath = "";
76-
}
77-
return new ServletEndpointRegistrar(servletPath + properties.getBasePath(),
77+
Set<String> cleanedPaths = getServletPaths(properties, servletPathProvider);
78+
return new ServletEndpointRegistrar(cleanedPaths,
7879
servletEndpointsSupplier.getEndpoints());
7980
}
8081

82+
private Set<String> getServletPaths(WebEndpointProperties properties,
83+
DispatcherServletPathProvider servletPathProvider) {
84+
Set<String> servletPaths = servletPathProvider.getServletPaths();
85+
return servletPaths.stream().map((p) -> {
86+
String path = cleanServletPath(p);
87+
return path + properties.getBasePath();
88+
}).collect(Collectors.toSet());
89+
}
90+
91+
private String cleanServletPath(String servletPath) {
92+
if (StringUtils.hasText(servletPath) && servletPath.endsWith("/")) {
93+
return servletPath.substring(0, servletPath.length() - 1);
94+
}
95+
return servletPath;
96+
}
97+
8198
}
8299

83100
@Configuration

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,23 @@ protected final boolean matches(HttpServletRequest request,
137137

138138
private RequestMatcher createDelegate(WebApplicationContext context) {
139139
try {
140-
String servletPath = getServletPath(context);
141-
RequestMatcherFactory requestMatcherFactory = (StringUtils
142-
.hasText(servletPath) ? new RequestMatcherFactory(servletPath)
143-
: RequestMatcherFactory.withEmptyServletPath());
140+
Set<String> servletPaths = getServletPaths(context);
141+
RequestMatcherFactory requestMatcherFactory = new RequestMatcherFactory(
142+
servletPaths);
144143
return createDelegate(context, requestMatcherFactory);
145144
}
146145
catch (NoSuchBeanDefinitionException ex) {
147146
return EMPTY_MATCHER;
148147
}
149148
}
150149

151-
private String getServletPath(WebApplicationContext context) {
150+
private Set<String> getServletPaths(WebApplicationContext context) {
152151
try {
153152
return context.getBean(DispatcherServletPathProvider.class)
154-
.getServletPath();
153+
.getServletPaths();
155154
}
156155
catch (NoSuchBeanDefinitionException ex) {
157-
return "";
156+
return Collections.singleton("");
158157
}
159158
}
160159

@@ -226,7 +225,7 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
226225
requestMatcherFactory, paths);
227226
if (this.includeLinks
228227
&& StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
229-
delegateMatchers.add(
228+
delegateMatchers.addAll(
230229
requestMatcherFactory.antPath(pathMappedEndpoints.getBasePath()));
231230
}
232231
return new OrRequestMatcher(delegateMatchers);
@@ -259,7 +258,8 @@ private String getEndpointId(Class<?> source) {
259258
private List<RequestMatcher> getDelegateMatchers(
260259
RequestMatcherFactory requestMatcherFactory, Set<String> paths) {
261260
return paths.stream()
262-
.map((path) -> requestMatcherFactory.antPath(path, "/**"))
261+
.flatMap(
262+
(path) -> requestMatcherFactory.antPath(path, "/**").stream())
263263
.collect(Collectors.toList());
264264
}
265265

@@ -276,7 +276,9 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
276276
WebEndpointProperties properties = context
277277
.getBean(WebEndpointProperties.class);
278278
if (StringUtils.hasText(properties.getBasePath())) {
279-
return requestMatcherFactory.antPath(properties.getBasePath());
279+
List<RequestMatcher> matchers = requestMatcherFactory
280+
.antPath(properties.getBasePath());
281+
return new OrRequestMatcher(matchers);
280282
}
281283
return EMPTY_MATCHER;
282284
}
@@ -288,25 +290,27 @@ protected RequestMatcher createDelegate(WebApplicationContext context,
288290
*/
289291
private static class RequestMatcherFactory {
290292

291-
private final String servletPath;
292-
293-
private static final RequestMatcherFactory EMPTY_SERVLET_PATH = new RequestMatcherFactory(
294-
"");
295-
296-
RequestMatcherFactory(String servletPath) {
297-
this.servletPath = servletPath;
298-
}
293+
private final Set<String> servletPaths = new LinkedHashSet<>();
299294

300-
RequestMatcher antPath(String... parts) {
301-
String pattern = (this.servletPath.equals("/") ? "" : this.servletPath);
302-
for (String part : parts) {
303-
pattern += part;
304-
}
305-
return new AntPathRequestMatcher(pattern);
295+
RequestMatcherFactory(Set<String> servletPaths) {
296+
this.servletPaths.addAll(servletPaths);
306297
}
307298

308-
static RequestMatcherFactory withEmptyServletPath() {
309-
return EMPTY_SERVLET_PATH;
299+
List<RequestMatcher> antPath(String... parts) {
300+
List<RequestMatcher> matchers = new ArrayList<>();
301+
this.servletPaths.stream().map((p) -> {
302+
if (StringUtils.hasText(p)) {
303+
return p;
304+
}
305+
return "";
306+
}).distinct().forEach((path) -> {
307+
String pattern = (path.equals("/") ? "" : path);
308+
for (String part : parts) {
309+
pattern += part;
310+
}
311+
matchers.add(new AntPathRequestMatcher(pattern));
312+
});
313+
return matchers;
310314
}
311315

312316
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.web.servlet;
1818

19+
import java.util.Collections;
20+
1921
import org.springframework.beans.factory.ListableBeanFactory;
2022
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
2123
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
@@ -95,7 +97,7 @@ public RequestContextFilter requestContextFilter() {
9597

9698
@Bean
9799
public DispatcherServletPathProvider childDispatcherServletPathProvider() {
98-
return () -> "";
100+
return () -> Collections.singleton("");
99101
}
100102

101103
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfigurationTests.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
1818

1919
import java.util.Collections;
20+
import java.util.LinkedHashSet;
21+
import java.util.Set;
2022

2123
import org.glassfish.jersey.server.ResourceConfig;
2224
import org.junit.Test;
@@ -48,27 +50,32 @@ public class ServletEndpointManagementContextConfigurationTests {
4850
.withUserConfiguration(TestConfig.class);
4951

5052
@Test
53+
@SuppressWarnings("unchecked")
5154
public void contextShouldContainServletEndpointRegistrar() {
5255
FilteredClassLoader classLoader = new FilteredClassLoader(ResourceConfig.class);
5356
this.contextRunner.withClassLoader(classLoader).run((context) -> {
5457
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
5558
ServletEndpointRegistrar bean = context
5659
.getBean(ServletEndpointRegistrar.class);
57-
String basePath = (String) ReflectionTestUtils.getField(bean, "basePath");
58-
assertThat(basePath).isEqualTo("/test/actuator");
60+
Set<String> basePaths = (Set<String>) ReflectionTestUtils.getField(bean,
61+
"basePaths");
62+
assertThat(basePaths).containsExactlyInAnyOrder("/test/actuator", "/actuator",
63+
"/foo/actuator");
5964
});
6065
}
6166

6267
@Test
68+
@SuppressWarnings("unchecked")
6369
public void servletPathShouldNotAffectJerseyConfiguration() {
6470
FilteredClassLoader classLoader = new FilteredClassLoader(
6571
DispatcherServlet.class);
6672
this.contextRunner.withClassLoader(classLoader).run((context) -> {
6773
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
6874
ServletEndpointRegistrar bean = context
6975
.getBean(ServletEndpointRegistrar.class);
70-
String basePath = (String) ReflectionTestUtils.getField(bean, "basePath");
71-
assertThat(basePath).isEqualTo("/actuator");
76+
Set<String> basePaths = (Set<String>) ReflectionTestUtils.getField(bean,
77+
"basePaths");
78+
assertThat(basePaths).containsExactly("/actuator");
7279
});
7380
}
7481

@@ -91,7 +98,13 @@ public ServletEndpointsSupplier servletEndpointsSupplier() {
9198

9299
@Bean
93100
public DispatcherServletPathProvider servletPathProvider() {
94-
return () -> "/test";
101+
return () -> {
102+
Set<String> paths = new LinkedHashSet<>();
103+
paths.add("/");
104+
paths.add("/test");
105+
paths.add("/foo/");
106+
return paths;
107+
};
95108
}
96109

97110
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.springframework.boot.actuate.autoconfigure.security.servlet;
1818

1919
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.LinkedHashSet;
2022
import java.util.List;
2123

2224
import javax.servlet.http.HttpServletRequest;
@@ -76,23 +78,23 @@ public void toAnyEndpointShouldNotMatchOtherPath() {
7678
@Test
7779
public void toAnyEndpointWhenServletPathNotEmptyShouldMatch() {
7880
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
79-
assertMatcher(matcher, "/actuator", "/spring").matches("/spring",
80-
"/actuator/foo");
81-
assertMatcher(matcher, "/actuator", "/spring").matches("/spring",
82-
"/actuator/bar");
83-
assertMatcher(matcher, "/actuator", "/spring").matches("/spring", "/actuator");
84-
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("/spring",
85-
"/actuator/baz");
86-
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("", "/actuator/foo");
81+
assertMatcher(matcher, "/actuator", "/spring", "/admin").matches("/actuator/foo",
82+
"/spring", "/admin");
83+
assertMatcher(matcher, "/actuator", "/spring", "/admin").matches("/actuator/bar",
84+
"/spring", "/admin");
85+
assertMatcher(matcher, "/actuator", "/spring").matches("/actuator", "/spring");
86+
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("/actuator/baz",
87+
"/spring");
88+
assertMatcher(matcher, "/actuator", "/spring").doesNotMatch("/actuator/foo", "");
8789
}
8890

8991
@Test
9092
public void toAnyEndpointWhenDispatcherServletPathProviderNotAvailableUsesEmptyPath() {
9193
RequestMatcher matcher = EndpointRequest.toAnyEndpoint();
92-
assertMatcher(matcher, "/actuator", null).matches("/actuator/foo");
93-
assertMatcher(matcher, "/actuator", null).matches("/actuator/bar");
94-
assertMatcher(matcher, "/actuator", null).matches("/actuator");
95-
assertMatcher(matcher, "/actuator", null).doesNotMatch("/actuator/baz");
94+
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator/foo");
95+
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator/bar");
96+
assertMatcher(matcher, "/actuator", (String) null).matches("/actuator");
97+
assertMatcher(matcher, "/actuator", (String) null).doesNotMatch("/actuator/baz");
9698
}
9799

98100
@Test
@@ -219,8 +221,8 @@ private RequestMatcherAssert assertMatcher(RequestMatcher matcher, String basePa
219221
}
220222

221223
private RequestMatcherAssert assertMatcher(RequestMatcher matcher, String basePath,
222-
String servletPath) {
223-
return assertMatcher(matcher, mockPathMappedEndpoints(basePath), servletPath);
224+
String... servletPaths) {
225+
return assertMatcher(matcher, mockPathMappedEndpoints(basePath), servletPaths);
224226
}
225227

226228
private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
@@ -243,7 +245,7 @@ private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
243245
}
244246

245247
private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
246-
PathMappedEndpoints pathMappedEndpoints, String servletPath) {
248+
PathMappedEndpoints pathMappedEndpoints, String... servletPaths) {
247249
StaticWebApplicationContext context = new StaticWebApplicationContext();
248250
context.registerBean(WebEndpointProperties.class);
249251
if (pathMappedEndpoints != null) {
@@ -254,8 +256,9 @@ private RequestMatcherAssert assertMatcher(RequestMatcher matcher,
254256
properties.setBasePath(pathMappedEndpoints.getBasePath());
255257
}
256258
}
257-
if (servletPath != null) {
258-
DispatcherServletPathProvider pathProvider = () -> servletPath;
259+
if (servletPaths != null) {
260+
DispatcherServletPathProvider pathProvider = () -> new LinkedHashSet<>(
261+
Arrays.asList(servletPaths));
259262
context.registerBean(DispatcherServletPathProvider.class, () -> pathProvider);
260263
}
261264
return assertThat(new RequestMatcherAssert(context, matcher));
@@ -276,8 +279,8 @@ public void matches(String servletPath) {
276279
matches(mockRequest(servletPath));
277280
}
278281

279-
public void matches(String servletPath, String pathInfo) {
280-
matches(mockRequest(servletPath, pathInfo));
282+
public void matches(String pathInfo, String... servletPaths) {
283+
Arrays.stream(servletPaths).forEach((p) -> matches(mockRequest(p, pathInfo)));
281284
}
282285

283286
private void matches(HttpServletRequest request) {

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfigurationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public void contextShouldConfigureDispatcherServletPathProviderWithEmptyPath() {
6868
this.contextRunner
6969
.withUserConfiguration(WebMvcEndpointChildContextConfiguration.class)
7070
.run((context) -> assertThat(context
71-
.getBean(DispatcherServletPathProvider.class).getServletPath())
72-
.isEmpty());
71+
.getBean(DispatcherServletPathProvider.class).getServletPaths())
72+
.containsExactly(""));
7373
}
7474

7575
static class ExistingConfig {

0 commit comments

Comments
 (0)