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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy