Skip to content

Commit 3522714

Browse files
mbhavewilkinsona
authored andcommitted
Use endpoint mappings in CloudFoundry integration
Closes gh-35085
1 parent da10c4e commit 3522714

File tree

8 files changed

+125
-39
lines changed

8 files changed

+125
-39
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointHandlerMapping.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
2929
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
3030
import org.springframework.boot.actuate.endpoint.EndpointId;
31+
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
3132
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
3233
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
3334
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
@@ -56,12 +57,15 @@ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointH
5657

5758
private final EndpointLinksResolver linksResolver;
5859

60+
private final Collection<ExposableEndpoint<?>> allEndpoints;
61+
5962
CloudFoundryWebFluxEndpointHandlerMapping(EndpointMapping endpointMapping,
6063
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
6164
CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor,
62-
EndpointLinksResolver linksResolver) {
65+
Collection<ExposableEndpoint<?>> allEndpoints) {
6366
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, true);
64-
this.linksResolver = linksResolver;
67+
this.linksResolver = new EndpointLinksResolver(allEndpoints);
68+
this.allEndpoints = allEndpoints;
6569
this.securityInterceptor = securityInterceptor;
6670
}
6771

@@ -76,6 +80,10 @@ protected LinksHandler getLinksHandler() {
7680
return new CloudFoundryLinksHandler();
7781
}
7882

83+
Collection<ExposableEndpoint<?>> getAllEndpoints() {
84+
return this.allEndpoints;
85+
}
86+
7987
class CloudFoundryLinksHandler implements LinksHandler {
8088

8189
@Override

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundryActuatorAutoConfiguration.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
3434
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
3535
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
36-
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
3736
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
3837
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
3938
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
39+
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
4040
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
4141
import org.springframework.boot.actuate.health.HealthEndpoint;
4242
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
@@ -81,6 +81,8 @@
8181
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
8282
public class ReactiveCloudFoundryActuatorAutoConfiguration {
8383

84+
private static final String BASE_PATH = "/cloudfoundryapplication";
85+
8486
@Bean
8587
@ConditionalOnMissingBean
8688
@ConditionalOnAvailableEndpoint
@@ -116,9 +118,8 @@ public CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebFluxEndpointHand
116118
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
117119
allEndpoints.addAll(webEndpoints);
118120
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
119-
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
120-
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
121-
new EndpointLinksResolver(allEndpoints));
121+
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping(BASE_PATH), webEndpoints,
122+
endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
122123
}
123124

124125
private CloudFoundrySecurityInterceptor getSecurityInterceptor(WebClient.Builder webClientBuilder,
@@ -154,25 +155,33 @@ private CorsConfiguration getCorsConfiguration() {
154155
static class IgnoredPathsSecurityConfiguration {
155156

156157
@Bean
157-
WebFilterChainPostProcessor webFilterChainPostProcessor() {
158-
return new WebFilterChainPostProcessor();
158+
WebFilterChainPostProcessor webFilterChainPostProcessor(
159+
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
160+
return new WebFilterChainPostProcessor(handlerMapping);
159161
}
160162

161163
}
162164

163165
static class WebFilterChainPostProcessor implements BeanPostProcessor {
164166

167+
private final PathMappedEndpoints pathMappedEndpoints;
168+
169+
WebFilterChainPostProcessor(CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
170+
this.pathMappedEndpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints);
171+
}
172+
165173
@Override
166174
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
167175
if (bean instanceof WebFilterChainProxy) {
168-
return postProcess((WebFilterChainProxy) bean);
176+
return postProcess((WebFilterChainProxy) bean, this.pathMappedEndpoints);
169177
}
170178
return bean;
171179
}
172180

173-
private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
181+
private WebFilterChainProxy postProcess(WebFilterChainProxy existing, PathMappedEndpoints pathMappedEndpoints) {
182+
List<String> paths = getPaths(pathMappedEndpoints);
174183
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
175-
.pathMatchers("/cloudfoundryapplication/**");
184+
.pathMatchers(paths.toArray(new String[] {}));
176185
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
177186
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
178187
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
@@ -181,6 +190,14 @@ private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
181190
return new WebFilterChainProxy(ignoredRequestFilterChain, allRequestsFilterChain);
182191
}
183192

193+
private static List<String> getPaths(PathMappedEndpoints pathMappedEndpoints) {
194+
List<String> paths = new ArrayList<>();
195+
pathMappedEndpoints.getAllPaths().forEach((path) -> paths.add(path + "/**"));
196+
paths.add(BASE_PATH);
197+
paths.add(BASE_PATH + "/");
198+
return paths;
199+
}
200+
184201
}
185202

186203
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
3232
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
3333
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
34-
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
3534
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
3635
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
3736
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
37+
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
3838
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
3939
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
4040
import org.springframework.boot.actuate.health.HealthEndpoint;
@@ -66,6 +66,9 @@
6666
import org.springframework.security.config.annotation.web.builders.WebSecurity;
6767
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
6868
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
69+
import org.springframework.security.web.util.matcher.OrRequestMatcher;
70+
import org.springframework.security.web.util.matcher.RequestMatcher;
71+
import org.springframework.util.CollectionUtils;
6972
import org.springframework.web.cors.CorsConfiguration;
7073
import org.springframework.web.servlet.DispatcherServlet;
7174

@@ -85,6 +88,8 @@
8588
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
8689
public class CloudFoundryActuatorAutoConfiguration {
8790

91+
private static final String BASE_PATH = "/cloudfoundryapplication";
92+
8893
@Bean
8994
@ConditionalOnMissingBean
9095
@ConditionalOnAvailableEndpoint
@@ -122,8 +127,7 @@ public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServl
122127
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
123128
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
124129
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
125-
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
126-
new EndpointLinksResolver(allEndpoints));
130+
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
127131
}
128132

129133
private CloudFoundrySecurityInterceptor getSecurityInterceptor(RestTemplateBuilder restTemplateBuilder,
@@ -163,18 +167,32 @@ private CorsConfiguration getCorsConfiguration() {
163167
public static class IgnoredCloudFoundryPathsWebSecurityConfiguration {
164168

165169
@Bean
166-
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer() {
167-
return new IgnoredCloudFoundryPathsWebSecurityCustomizer();
170+
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer(
171+
CloudFoundryWebEndpointServletHandlerMapping handlerMapping) {
172+
return new IgnoredCloudFoundryPathsWebSecurityCustomizer(handlerMapping);
168173
}
169174

170175
}
171176

172177
@Order(SecurityProperties.IGNORED_ORDER)
173178
static class IgnoredCloudFoundryPathsWebSecurityCustomizer implements WebSecurityCustomizer {
174179

180+
private final PathMappedEndpoints pathMappedEndpoints;
181+
182+
IgnoredCloudFoundryPathsWebSecurityCustomizer(CloudFoundryWebEndpointServletHandlerMapping handlerMapping) {
183+
this.pathMappedEndpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints);
184+
}
185+
175186
@Override
176187
public void customize(WebSecurity web) {
177-
web.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**"));
188+
List<RequestMatcher> requestMatchers = new ArrayList<>();
189+
this.pathMappedEndpoints.getAllPaths()
190+
.forEach((path) -> requestMatchers.add(new AntPathRequestMatcher(path + "/**")));
191+
requestMatchers.add(new AntPathRequestMatcher(BASE_PATH));
192+
requestMatchers.add(new AntPathRequestMatcher(BASE_PATH + "/"));
193+
if (!CollectionUtils.isEmpty(requestMatchers)) {
194+
web.ignoring().requestMatchers(new OrRequestMatcher(requestMatchers));
195+
}
178196
}
179197

180198
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
3232
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
3333
import org.springframework.boot.actuate.endpoint.EndpointId;
34+
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
3435
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
3536
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
3637
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
@@ -61,14 +62,17 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
6162

6263
private final EndpointLinksResolver linksResolver;
6364

65+
private final Collection<ExposableEndpoint<?>> allEndpoints;
66+
6467
CloudFoundryWebEndpointServletHandlerMapping(EndpointMapping endpointMapping,
6568
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
6669
CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor,
67-
EndpointLinksResolver linksResolver) {
70+
Collection<ExposableEndpoint<?>> allEndpoints) {
6871
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, true,
6972
WebMvcAutoConfiguration.pathPatternParser);
7073
this.securityInterceptor = securityInterceptor;
71-
this.linksResolver = linksResolver;
74+
this.linksResolver = new EndpointLinksResolver(allEndpoints);
75+
this.allEndpoints = allEndpoints;
7276
}
7377

7478
@Override
@@ -82,6 +86,10 @@ protected LinksHandler getLinksHandler() {
8286
return new CloudFoundryLinksHandler();
8387
}
8488

89+
Collection<ExposableEndpoint<?>> getAllEndpoints() {
90+
return this.allEndpoints;
91+
}
92+
8593
class CloudFoundryLinksHandler implements LinksHandler {
8694

8795
@Override

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointIntegrationTests.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive;
1818

1919
import java.time.Duration;
20+
import java.util.ArrayList;
2021
import java.util.Arrays;
22+
import java.util.Collection;
2123
import java.util.Collections;
24+
import java.util.List;
2225
import java.util.Map;
2326
import java.util.function.Consumer;
2427

@@ -28,15 +31,16 @@
2831
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
2932
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException;
3033
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
34+
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
3135
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
3236
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
3337
import org.springframework.boot.actuate.endpoint.annotation.Selector;
3438
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
3539
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
3640
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
37-
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
3841
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
3942
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
43+
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
4044
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
4145
import org.springframework.boot.autoconfigure.AutoConfigurations;
4246
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
@@ -245,9 +249,10 @@ CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebEndpointServletHandlerM
245249
CorsConfiguration corsConfiguration = new CorsConfiguration();
246250
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
247251
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
248-
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"),
249-
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
250-
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
252+
Collection<ExposableWebEndpoint> webEndpoints = webEndpointDiscoverer.getEndpoints();
253+
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>(webEndpoints);
254+
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"), webEndpoints,
255+
endpointMediaTypes, corsConfiguration, interceptor, allEndpoints);
251256
}
252257

253258
@Bean

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
9595
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
9696
ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class));
9797

98+
private static final String BASE_PATH = "/cloudfoundryapplication";
99+
98100
@AfterEach
99101
void close() {
100102
HttpResources.reset();
@@ -176,21 +178,24 @@ void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
176178
@Test
177179
@SuppressWarnings("unchecked")
178180
void cloudFoundryPathsIgnoredBySpringSecurity() {
179-
this.contextRunner
181+
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
180182
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
181183
"vcap.application.cf_api:https://my-cloud-controller.com")
182184
.run((context) -> {
183185
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
184186
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
185187
.getField(chainProxy, "filters");
186-
Boolean cfRequestMatches = filters.get(0)
187-
.matches(MockServerWebExchange
188-
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
189-
.block(Duration.ofSeconds(30));
190-
Boolean otherRequestMatches = filters.get(0)
191-
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
192-
.block(Duration.ofSeconds(30));
188+
Boolean cfBaseRequestMatches = getMatches(filters, BASE_PATH);
189+
Boolean cfBaseWithTrailingSlashRequestMatches = getMatches(filters, BASE_PATH + "/");
190+
Boolean cfRequestMatches = getMatches(filters, BASE_PATH + "/test");
191+
Boolean cfRequestWithAdditionalPathMatches = getMatches(filters, BASE_PATH + "/test/a");
192+
Boolean otherCfRequestMatches = getMatches(filters, BASE_PATH + "/other-path");
193+
Boolean otherRequestMatches = getMatches(filters, "/some-other-path");
194+
assertThat(cfBaseRequestMatches).isTrue();
195+
assertThat(cfBaseWithTrailingSlashRequestMatches).isTrue();
193196
assertThat(cfRequestMatches).isTrue();
197+
assertThat(cfRequestWithAdditionalPathMatches).isTrue();
198+
assertThat(otherCfRequestMatches).isFalse();
194199
assertThat(otherRequestMatches).isFalse();
195200
otherRequestMatches = filters.get(1)
196201
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
@@ -200,6 +205,13 @@ void cloudFoundryPathsIgnoredBySpringSecurity() {
200205

201206
}
202207

208+
private static Boolean getMatches(List<SecurityWebFilterChain> filters, String urlTemplate) {
209+
Boolean cfBaseRequestMatches = filters.get(0)
210+
.matches(MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate).build()))
211+
.block(Duration.ofSeconds(30));
212+
return cfBaseRequestMatches;
213+
}
214+
203215
@Test
204216
void cloudFoundryPlatformInactive() {
205217
this.contextRunner

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfigurationTests.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class CloudFoundryActuatorAutoConfigurationTests {
7777
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
7878
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
7979

80+
private static String BASE_PATH = "/cloudfoundryapplication";
81+
8082
@Test
8183
void cloudFoundryPlatformActive() {
8284
this.contextRunner
@@ -168,20 +170,31 @@ void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
168170

169171
@Test
170172
void cloudFoundryPathsIgnoredBySpringSecurity() {
171-
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
173+
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
174+
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
172175
.run((context) -> {
173176
FilterChainProxy securityFilterChain = (FilterChainProxy) context
174177
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
175178
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
176-
MockHttpServletRequest request = new MockHttpServletRequest();
177-
request.setServletPath("/cloudfoundryapplication/my-path");
178179
assertThat(chain.getFilters()).isEmpty();
179-
assertThat(chain.matches(request)).isTrue();
180+
MockHttpServletRequest request = new MockHttpServletRequest();
181+
testCloudFoundrySecurity(request, BASE_PATH, chain);
182+
testCloudFoundrySecurity(request, BASE_PATH + "/", chain);
183+
testCloudFoundrySecurity(request, BASE_PATH + "/test", chain);
184+
testCloudFoundrySecurity(request, BASE_PATH + "/test/a", chain);
185+
request.setServletPath(BASE_PATH + "/other-path");
186+
assertThat(chain.matches(request)).isFalse();
180187
request.setServletPath("/some-other-path");
181188
assertThat(chain.matches(request)).isFalse();
182189
});
183190
}
184191

192+
private static void testCloudFoundrySecurity(MockHttpServletRequest request, String basePath,
193+
SecurityFilterChain chain) {
194+
request.setServletPath(basePath);
195+
assertThat(chain.matches(request)).isTrue();
196+
}
197+
185198
@Test
186199
void cloudFoundryPlatformInactive() {
187200
this.contextRunner.withPropertyValues()

0 commit comments

Comments
 (0)