spring-cloud / spring-cloud/spring-cloud-gateway

[WebFlux] XForwardedHeadersFilter emits overlapping X-Forwarded-Prefix values for chained path filters

Open
#4,236 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Describe the bug

When a WebFlux route applies more than one StripPrefix filter, Spring Cloud Gateway sends overlapping X-Forwarded-Prefix values to the downstream service.

For a request to /tenant/api/blue that is stripped to /blue, the gateway sends:

X-Forwarded-Prefix: /tenant/api,/api

A downstream Spring application with forwarded-header processing enabled combines those values and reconstructs /tenant/api/api as the context path instead of /tenant/api.

The client request in this example does not contain an X-Forwarded-Prefix header. Both values are produced by a single gateway while processing one route.

How to reproduce

Run the gateway on port 8080 with this route:

server:
  port: 8080

spring:
  cloud:
    gateway:
      server:
        webflux:
          trusted-proxies: ".*"
          routes:
            - id: chained-strip-prefix
              uri: http://localhost:8081
              predicates:
                - Path=/tenant/api/**
              filters:
                - StripPrefix=1
                - StripPrefix=1

Run a downstream Spring WebFlux application on port 8081 with forwarded-header processing enabled:

server:
  port: 8081
  forward-headers-strategy: framework

Add an endpoint that returns the path information seen by the downstream application:

@RestController
class PathController {

	@GetMapping("/blue")
	Map<String, String> path(ServerHttpRequest request) {
		RequestPath path = request.getPath();
		return Map.of(
				"contextPath", path.contextPath().value(),
				"pathWithinApplication", path.pathWithinApplication().value());
	}

}

Send a request through the gateway:

curl http://localhost:8080/tenant/api/blue

The configured filters change the request path as follows:

/tenant/api/blue
    -> /api/blue
    -> /blue

Actual behavior

The downstream request contains overlapping prefix values:

X-Forwarded-Prefix: /tenant/api,/api

The downstream application reports a duplicated context-path segment:

{
  "contextPath": "/tenant/api/api",
  "pathWithinApplication": "/blue"
}

Expected behavior

The gateway should send the external prefix removed from the final routed path once:

X-Forwarded-Prefix: /tenant/api

The downstream application should therefore report:

{
  "contextPath": "/tenant/api",
  "pathWithinApplication": "/blue"
}

Version

spring-cloud-gateway-server-webflux: 5.0.3-SNAPSHOT

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the WebFlux XForwardedHeadersFilter entry point and reproduce the chained StripPrefix route described in the issue. Add coverage for the /tenant/api/blue request and verify that the downstream request contains one X-Forwarded-Prefix value, /tenant/api, with the expected context path.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.