Rewrite the path your backend sees
Clients often call a path that exists for routing only. The orders backend serves /orders/42, but your clients call /api/v1/orders/42. proxy-rewrite changes the request on its way to the backend without the client noticing. This guide, the first of Shape requests and answers, puts proxy-rewrite on the route orders-v1 for the old path and strips the prefix. At the end, a request for /api/v1/orders/42 reaches the backend as /orders/42 with the host name the backend expects.
Before you start
- What your backend expects: here
/orders/42for a client's/api/v1/orders/42, and the host nameorders.internal. - The route
orders-v1, taking/api/v1/orders/*. If you created it in Share plugins between routes, keep it as it is and start at step 2. Otherwise step 1 creates it. - This guide starts from
orders-v1with no plugin. A plugin from another guide that this page does not name can change the answers below; remove it first or work on a copy of the route. - The address and port of the backend nodes, as in Route requests to a backend.
- The requests below call
/api/v1/orders/42. - The host name of your gateway. In the console it is the first part of the Address line on a route's Overview tab,
api.example.comin this page's examples; replace it in every request below. - The Editor or Environment administrator role in this environment.
Steps
1. Create a route for the path clients call
Select Routes, then New route. Set Name to orders-v1. Under Matching, type /api/v1/orders/* in Paths and press Enter. The route matches the path the client sends, before anything is rewritten.
Under Target, choose Nodes on this route and add the backend nodes as in Route requests to a backend. Select Create route.
2. Choose proxy-rewrite
Open orders-v1 under Routes, select its Plugins tab, then Add plugin at the top right of the tab. Open the Transformation category, or type proxy-rewrite in the search box. Select proxy-rewrite, then Configure.
3. Strip the prefix with a pattern
Under Regex URI, select Add entry. The entry has two boxes side by side. Type the pattern in the first and the replacement in the second.
| Box | Value | Meaning |
|---|---|---|
| Pattern | ^/api/v1/(.*) | ^ ties the pattern to the start of the path. (.*) captures everything after the prefix. |
| Replacement | /$1 | $1 is what the brackets captured: the rest of the path. |
Leave URI empty. A fixed URI, when set, wins over the pattern and sends every request to that one path.
4. Name the host and add the plugin
Set Host to orders.internal, the name your backend answers to. This is the Host header the backend reads, not the backend node's address. Leave the other fields as they are. Select Add plugin at the bottom of the panel. The plugin is saved like this:
{
"regex_uri": [
"^/api/v1/(.*)",
"/$1"
],
"host": "orders.internal"
}
Check it
Send a request for the old path, then the same request with a query string. The answer the client gets does not show what your backend received. Your backend's own access log does.
curl -i -L 'https://<gateway host>/api/v1/orders/42'
- Under /api/v1/orders/
- 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. - With a query string
- A query string the client sends stays attached:
/api/v1/orders/42?page=2arrives asGET /orders/42?page=2.
What to know
/api/v1/orders/*does not take/api/v1/ordersitself, so this route does not answer a request for it. List/api/v1/ordersas a second path when it has to answer too, as Route requests to a backend does for/orders.- A fixed URI replaces the whole path. On a route whose path ends in
/*, every request then reaches the backend with that one path. To keep the rest of the path, use the pattern. - The query string the client sent stays attached to the new path, whether the path is written plain or as a regular expression.
- When the route reaches the backend through a shared upstream whose Host passing is
rewrite, the upstream decides the host name and the setting here is not used. Set the host here for one route alone; set it on the upstream when every route of that upstream needs the same name.
Related
- Share plugins between routes: orders-v1 and orders-api on one service.
- Set headers on every answer: change the answer on its way back to the client.
- proxy-rewrite in the reference.