I have got a request with header from my proxy: X-Forwarded-Prefix: http://some-site?param=value
ForwardedHeaderTransformer concatenate header value with initial url which is incorrect and request breaks.
So, my question is - is it correct to send url params in x-forwarded-prefix header?
If you look at the Spring WebFlux source code for ForwardedHeaderTransformer
, you'll see how the X-Forwarded-Prefix
header is handled:
URI originalUri = request.getURI();
HttpHeaders headers = request.getHeaders();
URI uri = adaptFromForwardedHeaders(originalUri, headers);
builder.uri(uri);
String prefix = getForwardedPrefix(request);
if (prefix != null) {
builder.path(prefix + uri.getRawPath());
builder.contextPath(prefix);
}
This shows that the value of X-Forwarded-Prefix
is interpreted as a plain path prefix. It is directly prepended to the URI path and applied as the request's context path.
There is no URL parsing, and query strings are not expected here.
Let's say a client requests:
GET /api/users
The reverse proxy strips the path prefix /api
before forwarding the request to the backend, so the backend sees:
GET /users
To preserve the original client-visible prefix, the proxy adds:
X-Forwarded-Prefix: /api
Spring then reconstructs the full path via:
builder.path(prefix + uri.getRawPath());
Which becomes:
"/api" + "/users" -> "/api/users"
So if a header like this is used:
X-Forwarded-Prefix: http://some-site?foo=bar
Then Spring tries to build:
"http://some-site?foo=bar" + "/users" -> "http://some-site?foo=bar/users"
This results in a malformed URI and breaks request processing - as you've observed.
So, the X-Forwarded-Prefix
header is intended to carry a clean path prefix (e.g. /api/v1
). Including a full URL or query string in this header isn't supported by Spring's processing logic and can lead to invalid URI construction.
Side note: If you want to disable this behavior entirely, you can do it via configuration - no need to redefine the bean manually:
spring.web.forwarded.enabled: false
This disables automatic registration of ForwardedHeaderTransformer
, so X-Forwarded-*
headers will be ignored.
Alternatively, you can register the bean manually with .setRemoveOnly(true)
if you only want the headers to be stripped but not applied:
@Bean
public ForwardedHeaderTransformer forwardedHeaderTransformer() {
ForwardedHeaderTransformer transformer =
new ForwardedHeaderTransformer();
transformer.setRemoveOnly(true);
return transformer;
}