mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
140 lines
6.4 KiB
Plaintext
140 lines
6.4 KiB
Plaintext
As a request goes through a chain of proxies, request details such as the scheme, host,
|
|
port, remote address, and local address change. Proxies can insert headers that keep track of
|
|
the hops, and that can help to restore the request from the original client's perspective.
|
|
This allows an application to create self-reference links for external clients.
|
|
|
|
There are two alternatives for headers that proxies can use:
|
|
|
|
- {rfc-site}/rfc7239[RFC 7239] defines the `"Forwarded"` HTTP header, a single header with
|
|
individual attributes for each component in the chain of proxied requests with the
|
|
following syntax.
|
|
- `"X-Forwarded-"` prefixed headers are the original approach that predates the standard
|
|
and uses a separate header for each request component.
|
|
|
|
The Spring Framework supports both approaches. Most proxies today support the original
|
|
`"X-Forwarded"` headers only as a de facto standard.
|
|
|
|
WARNING: For maximum security, a proxy at the edge of trust must be configured to reset both
|
|
the standard `"Forwarded"` and `"X-Forwarded-"` headers regardless of which ones are chosen
|
|
for use. Likewise, when configuring forwarded header handling in Spring, you need to indicate
|
|
which type of headers to use. More on security considerations later in this section.
|
|
|
|
|
|
|
|
[[forwarded-headers-non-standard]]
|
|
=== X-Forwarded Headers
|
|
|
|
This section describes supported `"X-Forwarded"` headers.
|
|
|
|
[[x-forwarded-host]]
|
|
==== X-Forwarded-Host
|
|
|
|
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host[`X-Forwarded-Host: <host>`]
|
|
is a de-facto standard header that is used to communicate the original host to a
|
|
downstream server. For example, if a request of `https://example.com/resource` is sent to
|
|
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
|
|
`X-Forwarded-Host: example.com` can be sent to inform the server that the original host was `example.com`.
|
|
|
|
[[x-forwarded-port]]
|
|
==== X-Forwarded-Port
|
|
|
|
While not standard, `X-Forwarded-Port: <port>` is a de-facto standard header that is used to
|
|
communicate the original port to a downstream server. For example, if a request of
|
|
`https://example.com/resource` is sent to a proxy which forwards the request to
|
|
`http://localhost:8080/resource`, then a header of `X-Forwarded-Port: 443` can be sent
|
|
to inform the server that the original port was `443`.
|
|
|
|
[[x-forwarded-proto]]
|
|
==== X-Forwarded-Proto
|
|
|
|
While not standard, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto[`X-Forwarded-Proto: (https|http)`]
|
|
is a de-facto standard header that is used to communicate the original protocol (for example, https / http)
|
|
to a downstream server. For example, if a request of `https://example.com/resource` is sent to
|
|
a proxy which forwards the request to `http://localhost:8080/resource`, then a header of
|
|
`X-Forwarded-Proto: https` can be sent to inform the server that the original protocol was `https`.
|
|
|
|
[[x-forwarded-ssl]]
|
|
==== X-Forwarded-Ssl
|
|
|
|
While not standard, `X-Forwarded-Ssl: (on|off)` is a de-facto standard header that is used to communicate the
|
|
original protocol (for example, https / https) to a downstream server. For example, if a request of
|
|
`https://example.com/resource` is sent to a proxy which forwards the request to
|
|
`http://localhost:8080/resource`, then a header of `X-Forwarded-Ssl: on` to inform the server that the
|
|
original protocol was `https`.
|
|
|
|
[[x-forwarded-prefix]]
|
|
==== X-Forwarded-Prefix
|
|
|
|
While not standard, https://microsoft.github.io/reverse-proxy/articles/transforms.html#defaults[`X-Forwarded-Prefix: <prefix>`]
|
|
is a de-facto standard header that is used to communicate the original URL path prefix to a
|
|
downstream server.
|
|
|
|
Use of `X-Forwarded-Prefix` can vary by deployment scenario, and needs to be flexible to
|
|
allow replacing, removing, or prepending the path prefix of the target server.
|
|
|
|
_Scenario 1: Override path prefix_
|
|
|
|
[subs="-attributes"]
|
|
----
|
|
https://example.com/api/{path} -> http://localhost:8080/app1/{path}
|
|
----
|
|
|
|
The prefix is the start of the path before the capture group `+{path}+`. For the proxy,
|
|
the prefix is `/api` while for the server the prefix is `/app1`. In this case, the proxy
|
|
can send `X-Forwarded-Prefix: /api` to have the original prefix `/api` override the
|
|
server prefix `/app1`.
|
|
|
|
_Scenario 2: Remove path prefix_
|
|
|
|
At times, an application may want to have the prefix removed. For example, consider the
|
|
following proxy to server mapping:
|
|
|
|
[subs="-attributes"]
|
|
----
|
|
https://app1.example.com/{path} -> http://localhost:8080/app1/{path}
|
|
https://app2.example.com/{path} -> http://localhost:8080/app2/{path}
|
|
----
|
|
|
|
The proxy has no prefix, while applications `app1` and `app2` have path prefixes
|
|
`/app1` and `/app2` respectively. The proxy can send ``X-Forwarded-Prefix: `` to
|
|
have the empty prefix override server prefixes `/app1` and `/app2`.
|
|
|
|
[NOTE]
|
|
====
|
|
A common case for this deployment scenario is where licenses are paid per
|
|
production application server, and it is preferable to deploy multiple applications per
|
|
server to reduce fees. Another reason is to run more applications on the same server in
|
|
order to share the resources required by the server to run.
|
|
|
|
In these scenarios, applications need a non-empty context root because there are multiple
|
|
applications on the same server. However, this should not be visible in URL paths of
|
|
the public API where applications may use different subdomains that provides benefits
|
|
such as:
|
|
|
|
* Added security, for example, same origin policy
|
|
* Independent scaling of applications (different domain points to different IP address)
|
|
====
|
|
|
|
_Scenario 3: Insert path prefix_
|
|
|
|
In other cases, it may be necessary to prepend a prefix. For example, consider the
|
|
following proxy to server mapping:
|
|
|
|
[subs="-attributes"]
|
|
----
|
|
https://example.com/api/app1/{path} -> http://localhost:8080/app1/{path}
|
|
----
|
|
|
|
In this case, the proxy has a prefix of `/api/app1` and the server has a prefix of
|
|
`/app1`. The proxy can send `X-Forwarded-Prefix: /api/app1` to have the original prefix
|
|
`/api/app1` override the server prefix `/app1`.
|
|
|
|
[[x-forwarded-for]]
|
|
==== X-Forwarded-For
|
|
|
|
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For[`X-Forwarded-For: <address>`]
|
|
is a de-facto standard header that is used to communicate the original `InetSocketAddress` of the client to a
|
|
downstream server. For example, if a request is sent by a client at `[fd00:fefe:1::4]` to a proxy at
|
|
`192.168.0.1`, the "remote address" information contained in the HTTP request will reflect the actual address of the
|
|
client, not the proxy.
|