As a request goes through proxies such as load balancers the host, port, and scheme may change, and that makes it a challenge to create links that point to the correct host, port, and scheme from a client perspective.
{rfc-site}/rfc7239[RFC 7239] defines the Forwarded
HTTP header
that proxies can use to provide information about the original request.
There are other non-standard headers, too, including X-Forwarded-Host
, X-Forwarded-Port
,
X-Forwarded-Proto
, X-Forwarded-Ssl
, and X-Forwarded-Prefix
.
While not standard, 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
.
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
.
While not standard, X-Forwarded-Proto: (https|http)
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-Proto: https
can be sent to inform the server that the original protocol was https
.
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
.
While not standard, 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
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:
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:
|
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:
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
.