Skip to main content

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/42 for a client's /api/v1/orders/42, and the host name orders.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-v1 with 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.com in 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.

BoxValueMeaning
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:

The Add proxy-rewrite panel with the prefix to strip and the host the backend sees filled in.
proxy-rewrite · as the console saves it
{
"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
curl -i -L 'https://<gateway host>/api/v1/orders/42'
Under /api/v1/orders/
A request for /api/v1/orders/42 reaches the backend as GET /orders/42 with Host: 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=2 arrives as GET /orders/42?page=2.

What to know​

  • /api/v1/orders/* does not take /api/v1/orders itself, so this route does not answer a request for it. List /api/v1/orders as 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.
G8 dev