kong-advanced-router is a kong plugin that allows you to make an intermediate HTTP call and based on the response, the original request can be conditionally proxied to an upstream host.
kong-advanced-router
is a kong plugin that allows you to make an intermediate HTTP call and based on the response, the original request can be conditionally proxied to an upstream host.
Let’s say you want to proxy a request to fetch the orders of a user. The flow is:
Key | Default | Type | Required | Description |
---|---|---|---|---|
io_url | string | true | URL | |
io_http_method | GET | string | false | HTTP Method (GET, POST) |
io_request_template | string | true | Template of the I/O call in JSON. Must be a valid json string | |
http_connect_timeout | 5000 | number | false | HTTP Connect timeout (ms) |
http_send_timeout | 5000 | number | false | HTTP Send timeout (ms) |
http_read_timeout | 5000 | number | false | HTTP Read timeout (ms) |
cache_io_response | true | boolean | false | If the response received doesn’t change frequently, you can cache it in memory |
cache_ttl_header | string | true | Dynamically set the TTL of cached response using a response header | |
cache_identifier | string | true | Key in the request which uniquely identifies the intermediate HTTP request. This is used to create the cache key against which the response is cached | |
default_cache_ttl_sec | number | true | Default TTL if cache_ttl_header header is not present in the response |
Key | Default | Type | Required | Description |
---|---|---|---|---|
propositions_json | string | true | Array of conditions and URLs that are used to set the upstream URL. Must be a valid json string. The conditions should follow correct Lua syntax | |
variables | [string] | true | List of all the keys from the response that are used for creating conditions in propositions_json |
{
"body": {
"a": "headers.x" // Set from headers of original request
},
"headers": {
"b": "query.y" // Set from query string of original request
},
"query": {
"c": "headers.z",
"d": 1 // Set a constant value
}
}
Body, headers and query of the intermediate HTTP call can be composed from the headers and query of the incoming request and constant values.
[
{
"condition": "<condition 1>",
"upstream_url": "<Upstream URL 1>"
},
{
"condition": "<condition 2>",
"upstream_url": "<Upstream URL 2>"
},
{
"condition": "default",
"upstream_url": "<Default URL>"
}
]
All upstream_url
endpoints mentioned in propositions_json
should ideally have the same request and response signature. If response signature is different, clients need to implement the response handling logic.
luarocks install kong-advanced-router
You will also need to enable this plugin by any of the below ways:
By adding it to the list of enabled plugins using KONG_PLUGINS
environment variable
export KONG_PLUGINS=advanced-router
By adding it to the plugins
key in kong.conf
plugins=advanced-router
io_url
, io_http_method
, io_request_template
parameters from the config to prepare the intermediate HTTP call.cache_ttl_header
response header if cache_io_response
is set to true in the config.propositions_json
.upstream_url
of the condition that evaluates to true or to the default values if all conditions evaluate to false.upstream_url
and the io_url
with environment variables before using them. config = {
io_url = "http://user_service/user" ,
io_http_method = "GET",
io_request_template = "{\"body\":{\"id\":\"headers.user_id\"}}",
http_connect_timeout = 2000,
http_send_timeout = 2000,
http_read_timeout = 2000,
cache_io_response = true,
cache_ttl_header = "edge_ttl",
cache_identifier = "headers.user_id",
default_cache_ttl_sec = 10,
propositions_json = "[
{
\"condition\": \"extract_from_io_response('data.status') == 1\",
\"upstream_url\": \"http://order_service_a/orders\"
},
{
\"condition\": \"extract_from_io_response('data.status') == 2\",
\"upstream_url\": \"http://order_service_b/orders\"
},
{
\"condition\": \"default\",
\"upstream_url\": \"http://order_service_c/orders\"
}
]",
variables = {"data.status"},
}
For the above config applied on route /orders
. Suppose we make the below request
curl --location --request GET 'localhost:8000/orders' \
--header 'user_id: 1'
The plugin first makes the below I/O call.
curl --location --request GET 'http://user_service/user' \
--header 'Content-Type: application/json' \
--data-raw '{
"id" : 1
}'
Suppose the response received is
{
"data": {
"status": 2,
"name": "foo",
"city": "bar"
}
}
Now this data is used to evaluate the conditions given in propositions_json
. extract_from_io_response
is an abstraction that is used to extract values from the I/O call response body. In this case, the second condition evaluates to true i.e.
extract_from_io_response('data.status') == 2
Hence, the upstream url is set as http://order_service_b/orders
The below functions can be used to write conditions in propositions_json
extract_from_io_response(key)
- Returns the value of the provided key from the HTTP response body. Nested keys can be passed by concatenating with dot (.). Eg - data.status
get_timestamp_utc(datestring)
- Returns the UTC timestamp of a datestring. It internally uses the Tieske/date module. This can be used to write conditions based on the timestring data from the HTTP response.get_current_timestamp_utc
- Returns the current timestamp in UTC. This can be used to compare the time string in HTTP response body to current time.upstream_url
endpoints mentioned in propositions_json
should ideally have the same request and response signature. If response signature is different, clients need to implement the response handling logic.proposition_json
cannot have conditions with comparision to null
.