question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support webflux.base-path in StripFilter and possibly others

See original GitHub issue

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

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
spencergibbcommented, Jun 8, 2021

PRs welcome.

1reaction
kpeterbauercommented, Oct 7, 2022

PRs welcome.

This is a huge quagmire. I would happily provide a PR, but for a solid fix a view conceptual clarifications are necessary.

Look at this route configuration:

spring:
  cloud:
    gateway:
      routes:
      - id: remote-route
        uri: https://upstream-service
        predicates:
        - Path=/api/**
      - id: local-route
        uri: forward:/local/path
        predicates:
        - Path=/local/**

Now if a context-path (base-path) is defined, all given path patterns should continue to work, so they must be considered as app-local paths without context-path. The fix for the Path-predicate is trivial. The context-path must also be preserved for the local route.

But how shall the context-path be handled for the upstream service? Is it included by default, or is it stripped by default?

One could argue that all paths in the configuration are app-local paths without context-path, so the context-path should be stripped by default (in other words, the scope of the context-path is only the local gateway itself, without affecting outgoing routes).

On the other hand, this might cause confusion when looking at the full incoming and outgoing paths (request URIs), so it might be a valid strategy that the context-path has to be explicitly stripped with an additional “StripContextPath” filter.

Additionally, a lot of clarifications are necessary in the docs, e.g. for StripPrefix and all other components manipulating the path.

Any ideas?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Support webflux.base-path in StripFilter and possibly others
@spencergibb because looking at the stack trace, it looks like the issue is coming from Spring Gateway, not Spring Security. @Saljack , thanks....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found