Skip to content

Commit 307f3c3

Browse files
mbhavephilwebb
authored andcommitted
Use endpoint mappings in CloudFoundry integration
Closes gh-35411
1 parent 585286e commit 307f3c3

File tree

8 files changed

+126
-40
lines changed

8 files changed

+126
-40
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;
@@ -82,6 +82,8 @@
8282
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
8383
public class ReactiveCloudFoundryActuatorAutoConfiguration {
8484

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

125126
private CloudFoundrySecurityInterceptor getSecurityInterceptor(WebClient.Builder webClientBuilder,
@@ -155,25 +156,33 @@ private CorsConfiguration getCorsConfiguration() {
155156
static class IgnoredPathsSecurityConfiguration {
156157

157158
@Bean
158-
WebFilterChainPostProcessor webFilterChainPostProcessor() {
159-
return new WebFilterChainPostProcessor();
159+
WebFilterChainPostProcessor webFilterChainPostProcessor(
160+
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
161+
return new WebFilterChainPostProcessor(handlerMapping);
160162
}
161163

162164
}
163165

164166
private static class WebFilterChainPostProcessor implements BeanPostProcessor {
165167

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

174-
private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
182+
private WebFilterChainProxy postProcess(WebFilterChainProxy existing, PathMappedEndpoints pathMappedEndpoints) {
183+
List<String> paths = getPaths(pathMappedEndpoints);
175184
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
176-
.pathMatchers("/cloudfoundryapplication/**");
185+
.pathMatchers(paths.toArray(new String[] {}));
177186
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
178187
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
179188
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
@@ -182,6 +191,14 @@ private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
182191
return new WebFilterChainProxy(ignoredRequestFilterChain, allRequestsFilterChain);
183192
}
184193

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

187204
}

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

@@ -86,6 +89,8 @@
8689
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
8790
public class CloudFoundryActuatorAutoConfiguration {
8891

92+
private static final String BASE_PATH = "/cloudfoundryapplication";
93+
8994
@Bean
9095
@ConditionalOnMissingBean
9196
@ConditionalOnAvailableEndpoint
@@ -123,8 +128,7 @@ public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServl
123128
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
124129
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
125130
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
126-
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
127-
new EndpointLinksResolver(allEndpoints));
131+
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
128132
}
129133

130134
private CloudFoundrySecurityInterceptor getSecurityInterceptor(RestTemplateBuilder restTemplateBuilder,
@@ -164,18 +168,32 @@ private CorsConfiguration getCorsConfiguration() {
164168
public static class IgnoredCloudFoundryPathsWebSecurityConfiguration {
165169

166170
@Bean
167-
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer() {
168-
return new IgnoredCloudFoundryPathsWebSecurityCustomizer();
171+
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer(
172+
CloudFoundryWebEndpointServletHandlerMapping handlerMapping) {
173+
return new IgnoredCloudFoundryPathsWebSecurityCustomizer(handlerMapping);
169174
}
170175

171176
}
172177

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

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

181199
}

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;
@@ -60,13 +61,16 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
6061

6162
private final EndpointLinksResolver linksResolver;
6263

64+
private final Collection<ExposableEndpoint<?>> allEndpoints;
65+
6366
CloudFoundryWebEndpointServletHandlerMapping(EndpointMapping endpointMapping,
6467
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
6568
CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor,
66-
EndpointLinksResolver linksResolver) {
69+
Collection<ExposableEndpoint<?>> allEndpoints) {
6770
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, true);
6871
this.securityInterceptor = securityInterceptor;
69-
this.linksResolver = linksResolver;
72+
this.linksResolver = new EndpointLinksResolver(allEndpoints);
73+
this.allEndpoints = allEndpoints;
7074
}
7175

7276
@Override
@@ -80,6 +84,10 @@ protected LinksHandler getLinksHandler() {
8084
return new CloudFoundryLinksHandler();
8185
}
8286

87+
Collection<ExposableEndpoint<?>> getAllEndpoints() {
88+
return this.allEndpoints;
89+
}
90+
8391
class CloudFoundryLinksHandler implements LinksHandler {
8492

8593
@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;
@@ -184,9 +188,10 @@ CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebEndpointServletHandlerM
184188
CorsConfiguration corsConfiguration = new CorsConfiguration();
185189
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
186190
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
187-
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"),
188-
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
189-
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
191+
Collection<ExposableWebEndpoint> webEndpoints = webEndpointDiscoverer.getEndpoints();
192+
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>(webEndpoints);
193+
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"), webEndpoints,
194+
endpointMediaTypes, corsConfiguration, interceptor, allEndpoints);
190195
}
191196

192197
@Bean

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

Lines changed: 21 additions & 9 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();
@@ -170,26 +172,36 @@ void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
170172
@Test
171173
@SuppressWarnings("unchecked")
172174
void cloudFoundryPathsIgnoredBySpringSecurity() {
173-
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
174-
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
175+
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new).withPropertyValues("VCAP_APPLICATION:---",
176+
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
177+
.run((context) -> {
175178
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
176179
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
177180
.getField(chainProxy, "filters");
178-
Boolean cfRequestMatches = filters.get(0)
179-
.matches(MockServerWebExchange
180-
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
181-
.block(Duration.ofSeconds(30));
182-
Boolean otherRequestMatches = filters.get(0)
183-
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
184-
.block(Duration.ofSeconds(30));
181+
Boolean cfBaseRequestMatches = getMatches(filters, BASE_PATH);
182+
Boolean cfBaseWithTrailingSlashRequestMatches = getMatches(filters, BASE_PATH + "/");
183+
Boolean cfRequestMatches = getMatches(filters, BASE_PATH + "/test");
184+
Boolean cfRequestWithAdditionalPathMatches = getMatches(filters, BASE_PATH + "/test/a");
185+
Boolean otherCfRequestMatches = getMatches(filters, BASE_PATH + "/other-path");
186+
Boolean otherRequestMatches = getMatches(filters, "/some-other-path");
187+
assertThat(cfBaseRequestMatches).isTrue();
188+
assertThat(cfBaseWithTrailingSlashRequestMatches).isTrue();
185189
assertThat(cfRequestMatches).isTrue();
190+
assertThat(cfRequestWithAdditionalPathMatches).isTrue();
191+
assertThat(otherCfRequestMatches).isFalse();
186192
assertThat(otherRequestMatches).isFalse();
187193
otherRequestMatches = filters.get(1)
188194
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
189195
.block(Duration.ofSeconds(30));
190196
assertThat(otherRequestMatches).isTrue();
191197
});
198+
}
192199

200+
private static Boolean getMatches(List<SecurityWebFilterChain> filters, String urlTemplate) {
201+
Boolean cfBaseRequestMatches = filters.get(0)
202+
.matches(MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate).build()))
203+
.block(Duration.ofSeconds(30));
204+
return cfBaseRequestMatches;
193205
}
194206

195207
@Test

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.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
@@ -160,20 +162,31 @@ void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
160162

161163
@Test
162164
void cloudFoundryPathsIgnoredBySpringSecurity() {
163-
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
165+
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
166+
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
164167
.run((context) -> {
165168
FilterChainProxy securityFilterChain = (FilterChainProxy) context
166169
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
167170
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
168-
MockHttpServletRequest request = new MockHttpServletRequest();
169-
request.setServletPath("/cloudfoundryapplication/my-path");
170171
assertThat(chain.getFilters()).isEmpty();
171-
assertThat(chain.matches(request)).isTrue();
172+
MockHttpServletRequest request = new MockHttpServletRequest();
173+
testCloudFoundrySecurity(request, BASE_PATH, chain);
174+
testCloudFoundrySecurity(request, BASE_PATH + "/", chain);
175+
testCloudFoundrySecurity(request, BASE_PATH + "/test", chain);
176+
testCloudFoundrySecurity(request, BASE_PATH + "/test/a", chain);
177+
request.setServletPath(BASE_PATH + "/other-path");
178+
assertThat(chain.matches(request)).isFalse();
172179
request.setServletPath("/some-other-path");
173180
assertThat(chain.matches(request)).isFalse();
174181
});
175182
}
176183

184+
private static void testCloudFoundrySecurity(MockHttpServletRequest request, String basePath,
185+
SecurityFilterChain chain) {
186+
request.setServletPath(basePath);
187+
assertThat(chain.matches(request)).isTrue();
188+
}
189+
177190
@Test
178191
void cloudFoundryPlatformInactive() {
179192
this.contextRunner.withPropertyValues()

0 commit comments

Comments
 (0)