Describe the bug
StripPrefix filter (and maybe RewritePath too) isn't able to remove a contextPath if there is any set. It started with upgrading to Spring Boot 2.3. I think it is connected with introducing spring.webflux.base-path but I don't use it. I use ForwardedHeaderTransformer for adding na prefix from a header X-Forwarded-Prefix (SCG runs behind NGINX proxy). This transformer sets contextPath to prefix builder.contextPath(prefix). StripPrefix filter strips only in path and not in contextPath request.mutate().path(newPath) and then it throws an IllegalArgumentException if build() method is called.
See a stacktrace:
java.lang.IllegalArgumentException: Invalid contextPath '/admin': must match the start of requestPath: '/sba/'
at org.springframework.http.server.DefaultRequestPath.validateContextPath(DefaultRequestPath.java:82)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.oauth2.client.web.server.authentication.OAuth2LoginAuthenticationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.oauth2.client.web.server.OAuth2AuthorizationRequestRedirectWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.cloud.sleuth.instrument.web.TraceWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/admin/sba/" [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.http.server.DefaultRequestPath.validateContextPath(DefaultRequestPath.java:82)
at org.springframework.http.server.DefaultRequestPath.initContextPath(DefaultRequestPath.java:57)
at org.springframework.http.server.DefaultRequestPath.<init>(DefaultRequestPath.java:42)
at org.springframework.http.server.RequestPath.parse(RequestPath.java:60)
at org.springframework.http.server.reactive.AbstractServerHttpRequest.<init>(AbstractServerHttpRequest.java:81)
at org.springframework.http.server.reactive.DefaultServerHttpRequestBuilder$MutatedServerHttpRequest.<init>(DefaultServerHttpRequestBuilder.java:197)
at org.springframework.http.server.reactive.DefaultServerHttpRequestBuilder.build(DefaultServerHttpRequestBuilder.java:136)
at org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory$1.filter(StripPrefixGatewayFilterFactory.java:71)
at org.springframework.cloud.gateway.filter.OrderedGatewayFilter.filter(OrderedGatewayFilter.java:44)
at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.lambda$filter$0(FilteringWebHandler.java:118)
Sample
Configuration
spring:
cloud:
gateway:
routes:
- id: sba
uri: http://localhost:20010
predicates:
- Path=/admin/sba/**
filters:
- StripPrefix=1
Enable ForwardedHeaderTransformer
@Configuration
public class ForwardedHeaderConfiguration {
@Bean
public ForwardedHeaderTransformer forwardedHeaderTransformer() {
return new ForwardedHeaderTransformerImpl();
}
}
Call http://localhost:{applicationPort}/sba with X-Forwarded-Prefix: /admin
Describe the bug
StripPrefix filter (and maybe RewritePath too) isn't able to remove a contextPath if there is any set. It started with upgrading to Spring Boot 2.3. I think it is connected with introducing
spring.webflux.base-pathbut I don't use it. I useForwardedHeaderTransformerfor adding na prefix from a headerX-Forwarded-Prefix(SCG runs behind NGINX proxy). This transformer sets contextPath to prefixbuilder.contextPath(prefix). StripPrefix filter strips only in path and not in contextPathrequest.mutate().path(newPath)and then it throws an IllegalArgumentException ifbuild()method is called.See a stacktrace:
Sample
Configuration
Enable ForwardedHeaderTransformer
Call
http://localhost:{applicationPort}/sbawithX-Forwarded-Prefix: /admin