URL rewriting in Kong

Peter Kim
3 min readJan 14, 2020

--

Little Big Painting, Roy Lichtenstein @ Whitney Museum of American Art. https://whitney.org/collection/works/2924

A common requirement for APIs is the rewrite the published URL to a different URL for the upstream service’s endpoint. For example, due to legacy reasons, your upstream endpoint may have a base URI like /api/oilers/. However, you want your publicly accessible API endpoint to now be named /titans/api.

Simple re-writing

When you configure a route with a path, the part of the URI after the path will automatically be appended to the path value of the upstream service. In this example, we’ll use httpbin.org/anything as our mock service and HTTPie as our command-line client.

Create a service with path /anything/api/oilers:

http POST :8001/services name=runandshoot4ever host=httpbin.org path=/anything/api/oilers

Create a route with path /titans/api:

http POST :8001/services/runandshoot4ever/routes name=tannehill paths:='["/titans/api"]'

Make an API call to /titans/api:

http :8000/titans/api/players/search\?q=henry

Response (see how the url is translated with a new base path of /anything/api/oilers):

{
"args": {
"q": "henry"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "HTTPie/2.0.0",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": "172.23.0.1, 74.66.140.21, 172.23.0.1",
"url": "https://localhost/anything/api/oilers/players/search?q=henry"
}

More complex re-writing

Kong can also handle more complex URL rewriting cases by using regex capture groups in our route path and the Request Transformer Advanced plugin (bundled with Kong Enterprise). Instead of simply replacing the base URI from /api/oilers to /titans/api, our requirement is to replace /api/<function>/oilers with /titans/api/<function>.

Setup

Create a new service:

http POST :8001/services name=warrenmoon4ever host=httpbin.org

Capture URI string

Next, we must configure a route to capture the parts of the URI string past that need to be preserved. Kong supports specifying regex capture groups in the paths config parameter which can be referenced by plugins: https://docs.konghq.com/1.4.x/proxy/#capturing-groups

In our example, we need to set the paths parameter of our route to parse out the function name and capture the rest of the path separately.

Create a route with paths with capturing groups:

http POST :8001/services/warrenmoon4ever/routes name=mariotta paths:='["/titans/api/(?<function>\\\S+?)/(?<path>\\\S+)"]'

Configure transform using the Request Transformer plugin

The next step is to configure the Request Transformer Advanced plugin on the route. Using our example, we need to set the config.replace.uri parameter to inject the function name in between /api and /oilers, then append the rest of the URI.

Create a plugin configuration on the route (replace route ID value with the actual ID from the route create above):

http --form POST :8001/routes/02e1ca00-be63-4f21-80bb-b8d5189525e3/plugins name=request-transformer-advanced config.replace.uri="/anything/api/\$(uri_captures['function'])/oilers/\$(uri_captures['path'])"

Now, when we make a request to /titans/api/search/players?q=henry, the request will be translated to /api/search/oilers/players?q=henry.

Make an API call to /titans/api:

http :8000/titans/api/search/players\?q=henry

Response (see how the url is translated):

{
"args": {
"q": "henry"
},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "HTTPie/2.0.0",
"X-Forwarded-Host": "localhost"
},
"json": null,
"method": "GET",
"origin": "172.23.0.1, 74.66.140.21, 172.23.0.1",
"url": "https://localhost/anything/api/search/oilers/players?q=henry"
}

Conclusion

This is just scratching the surface of the powerful capabilities Kong offers for helping enterprises manage APIs. Learn more at konghq.com!

--

--

Peter Kim
Peter Kim

Written by Peter Kim

Urbanist, bicycle enthusiast, cheap eats connoisseur. Product Manager @prisma. Opinions expressed here are mine alone.

Responses (1)