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

[Server MVC] XForwardedRequestHeadersFilter emits overlapping X-Forwarded-Prefix values for chained path filters

Open
#4,237 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 Server MVC 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:
        webmvc:
          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-webmvc: 5.0.3-SNAPSHOT

Related

This is the Server MVC counterpart of #4236, which reports the same behavior in the WebFlux server.

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 with the Server MVC XForwardedRequestHeadersFilter and reproduce the chained StripPrefix route described in the issue. Done means the downstream request contains only X-Forwarded-Prefix: /tenant/api and reports contextPath /tenant/api with pathWithinApplication /blue.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.