How to Dynamically Route Requests With Kong Enterprise
Having worked with many customers and prospects at Kong, one of the main requirements we often hear is how to handle dynamic routing based on the URL and headers. In this blog post, I will cover different use cases we come across for dynamic routing and how Kong can address them.
The default behavior of an API gateway is to route the incoming request to the appropriate upstream service.
If you are new to Kong, a Service object represents the upstream API or Service. The main attribute of a Service is the URL (where Kong should proxy traffic to), which can be set as a single string URL or by specifying the protocol, host, port and path properties.
Steps to Route Kong Enterprise Requests
To make requests to services via Kong, they first need to be exposed by routes. A single service can have many routes to allow different policies to be applied to different clients/consumers accessing the same Service. After configuring services and routes, clients make requests to routes, and the requests will be proxied to services.
One common use case for dynamic routing is to rewrite the requested URL to a different URL for the upstream. This is helpful in instances where the structure of the service's URL has changed, but we don't want to change or impact how the client calls the service. For this use case, Kong can make the change transparent to the client by enabling URL rewriting. My colleague, Peter Kim, wrote a great blog post on this subject that I invite you to read.
Let’s review another use case. Based on a specific header, route the request to a different upstream. This scenario is useful when a new version of an API is available.
Let's walk through an example using Kong Manager to set up the scenario. Note Kong can also be managed through the Admin API as well as declaratively.
Say our API will be represented by a service called httpbin, which forwards requests to an upstream with URL httpbin.org.
Launch Kong Manager, click on the Workspace you want to work with, select Services and click Add a Service.
Create myfirstRoute
Let's now create a route called "myfirstRoute" to access the service through Kong when a path of /requestByheader is provided. Meaning, when a request to Kong is made with path /requestByheader, Kong will forward the request to the httpbin service.
In the httpbin service, click Add route, name the route "myfirstRoute" and under Path(s), enter /reequestByheader.
Let's confirm the service and route are working correctly by using Kong Studio to send a request to Kong and the route we created. As expected, the request is forwarded to the upstream httpbin.org.
Enable Dynamic Routing
To enable the dynamic routing use case based on header values, let’s enable the route-by-header plugin on this route. For those new to Kong, a plugin allows Kong to apply policy to request and responses. For this scenario, let's configure the plugin to route to a different upstream, httpbin2, if a header with version "v2" is part of the request.
Let's use the Admin API to configure the plugin on the route we created. The following command configures the route-by-header plug-in on the myfirstRoute to route to the upstream httpbin2 when a header version:v2 is part of the request.
curl -i -X POST http://<kong_host>:8001/routes/myfirstRoute/plugins -H ‘Content-Type: application/json’ –data ‘{"name": "route-by-header", "config": {"rules":[{"condition": {"version":"v2"}, "upstream_name": "httpbin2"}]}}’
Sending the same request as before using Kong Studio, but this time with a header of version v2, sends the request to httpbin2 instead of httpbin.org.
Many customers use this capability to enable A/B testing or to slowly migrate users from one version to another.
Target Upstream Requests
Another use case is that you may want to provide the target upstream in your request (in the URI, query parameters or in a header). One possible use case is, for example, the same service is hosted on different instances but specific to an end customer. One of our telecommunications customers providing network managed services uses this scenario to give access to the right EMS (Element Management System) to their end customers. The service provided is the same but on a different EMS. The route-transformer-advanced plugin is the most appropriate to do so, as it allows it to transform the routing on the fly in Kong, changing the upstream server, port or path to hit.
Case A: Using a Header
On the previous same route (myfirstRoute), instead of enabling the route-by-header plugin, we enable the plugins route-transformer-advanced.
For now on, for this path (/requestByheader), Kong expects a header called "mytarget" with the target host value.
Case B: Using a Part of the URI (Capture URI String)
First, we need to modify the path in the route. Paths accept regex (as explained in more details here) to allow capturing groups.
Let’s create another route with a path "/requestByUri/(?<target>\w+)"
Apply the route-transformer-advanced plugins using the capture URI method.
And voilà …
One comment here: Some may object that the upstream target may be unknown from the client/consumer side and therefore this won’t be of any use. In that particular case, I recommend that you read my next post on the usage of the serverless function plugin.