spring-cloud / spring-cloud/spring-cloud-gateway
Support webflux.base-path in StripFilter and possibly others
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 4.9k
- Forks
- 3.5k
- Avg merge
- 20h 57m
- Merged PRs (30d)
- 8
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with StripPrefixGatewayFilterFactory at the failing build path shown in the stack trace, then trace how ForwardedHeaderTransformer sets contextPath and how request mutation handles the path. Reproduce the sample route with spring.webflux.base-path or X-Forwarded-Prefix, and check whether RewritePath is affected too. Done means the request no longer throws when the context path is present and prefix stripping behaves correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring, spring-boot
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100