proxy-rewrite
Rewrites the request URI, method, host and headers before proxying.
proxy-rewritePriority 1008What it does
proxy-rewrite changes the request the backend receives: the path, by a fixed URI or a pattern, the Host header, the method and the headers. The client is not redirected, and the request still goes to the route's upstream.
The route matches the path the client sends, before anything is rewritten, so its Path stays the one clients call. A query string the client sent stays attached to the new path.
When to use it
- A prefix that exists for routing only,
/api/v1for example, and must not reach the backend, while the rest of the path does. - A backend that reads the Host header and needs a name of its own, not the one the client used.
- A backend that expects another path than the one clients call.
- A header the backend must always see with your value, whatever the client sent, or one the client sends, a cookie for example, that must never reach it.
Not for sending the client to another address with a redirect — see redirect (Redirects requests to another URI or to HTTPS), changing the answer the client gets, its status, headers or body — see response-rewrite (Rewrites the response status, headers and body) or sending the request to another upstream — see traffic-split (Splits traffic between upstreams by weight and match rules).
Guides
Pages that walk through a job with proxy-rewrite, step by step.
- Rewrite the path your backend seesStrip a prefix from the path and set the Host header before the request reaches the backend.
Set it up
Remove the /api/v1 prefix and send the Host name the backend expects
The route keeps the path clients call, /api/v1/orders/*; only the request the backend receives changes.
Fill Regex URI as in the JSON below and set Host to orders.internal.
{
"regex_uri": [
"^/api/v1/(.*)",
"/$1"
],
"host": "orders.internal"
}
What you will see
- A request for
/api/v1/orders/42reaches the backend asGET /orders/42withHost: orders.internal: the prefix is gone and the rest of the path stays. - A query string the client sends stays attached:
/api/v1/orders/42?page=2arrives asGET /orders/42?page=2.
More scenarios
Rewrite the path and the Host header sent to the backend
The request still goes to the route's own upstream; only the path and the Host header it carries change.
Set URI to /v2/orders and set Host to orders.internal.
{
"uri": "/v2/orders",
"host": "orders.internal"
}
What you will see
- A request for the route's path with
?page=2reaches the backend asGET /v2/orders?page=2withHost: orders.internal: the query string stays, the method stays. X-Tenant: acmeand the body go on as the client sent them, and aPOSTarrives asPOST /v2/orders.
Remove the /api/v2 prefix before the request reaches the backend
Clients keep calling the route's own path; the pattern is read against the path alone, and the query string stays as it is.
Fill Regex URI as in the JSON below.
{
"regex_uri": [
"^/api/v2/(.*)",
"/$1"
]
}
What you will see
- A request for
/api/v2/orders/42?page=2reaches the backend asGET /orders/42?page=2: the prefix is gone and the query string stays.
Stamp one value on a header, whatever the client sent
The plain shape, a header name with one value, writes the header over the value the client sent, the way Set does in the other shape.
Choose One value per header and fill Headers as in the JSON below.
{
"headers": {
"X-Tenant": "acme"
}
}
What you will see
- The backend sees
X-Tenant: acmeand nothing of the value the client sent under that name.
Set, add and remove request headers before the backend sees them
Set writes the header over whatever the client sent, Add appends your value beside the one the client sent, and Remove drops the header.
Choose Add, set and remove and fill Headers as in the JSON below.
{
"headers": {
"add": {
"X-Request-Source": "gateway"
},
"remove": [
"Cookie"
],
"set": {
"X-Forwarded-Proto": "https"
}
}
}
What you will see
- The backend sees
X-Forwarded-Protoashttpswhatever the client sent. - A client that sends its own
X-Request-Sourcekeeps it: the backend sees both values,clientfirst andgatewayafter it. - No
Cookiereaches the backend.
Things to know
- URI — A fixed URI replaces the whole path: on a route whose Path ends in
/*, every request the route takes reaches the backend with that one path, whatever followed the prefix. To keep the rest of the path, use Regex URI. - URI — The query string the client sent stays attached to the new path.
- Regex URI —
$1in the replacement is what the first bracket of the pattern matched. The pattern is read against the path without its query string, which stays attached afterwards. - Headers — Two shapes, never mixed in one configuration: one value per header writes each header over what the client sent, and Add, set and remove is the three lists.
- Add — Add keeps the value the client sent and appends yours, so the backend sees both; to replace it, use Set.
Settings
The fields as the console shows them, section by section.
uristringThe path the request is forwarded with, in place of the one the client sent.
pattern
^\/.*/api/v2/ordersregex_uriarray of stringsRewrites the client's path by a pattern: the first part matches, the second builds the new path. A plain URI, when set, wins over it.
hoststringThe Host header sent to the upstream, such as orders.internal, while the request still goes to the upstream's own nodes. An upstream whose Host passing is node or rewrite overrides it: the node address or the upstream's own host is sent instead.
pattern
^[0-9a-zA-Z-.]+(:\d{1,5})?$backend.internalmethodstringThe HTTP method the request is forwarded with.
Choose one:
One value per header
headersobjectHeaders added to, set on or removed from the request before it is forwarded. An object whose keys are a name without a colon, each with a string or number as its value.
Add, set and remove
headersobjectHeaders added to, set on or removed from the request before it is forwarded.
headers.addobjectAn object whose keys are a name without a colon, each with a string or number or array as its value.
{"X-Request-Source":"gateway"}headers.removearray of stringsheaders.setobjectAn object whose keys are a name without a colon, each with a string or number or array as its value.
{"X-Forwarded-Proto":"https"}use_real_request_uri_unsafebooleandefault falseForwards the path exactly as the client sent it, without the normalisation this plugin otherwise applies (x/../y becomes y). A URI set above still wins over it. Leave it off unless the upstream needs the raw path: dot segments and encoded slashes then reach it untouched.