Hi. I and my team have been using Kong extensively for over two years now as our API gateway and Kubernetes ingress controller. But we are now reevaluating our routing strategy and are trying to use a custom plugin to prevent any breaking changes, but it is not having the behaviour I am expecting.
Background
Early on we adopted a straightforward routing approach where each of our services was given its own Route (ingress) based on a unique prefix. This route was configured in Kong with strip_path=true
(at the time this was the default behaviour of KIC).
For example:
The foobar
microservice is given the prefix foo
. Client requests are made for /foo/bar
and /foo/baz
, Kong matches them to the foo
route and makes upstream requests for /bar
and /baz
respectively.
This is obviously a very coarse approach and we are doing away with it for a variety of reasons. Essentially we would like to have the flexibility of working with more of the path without stripping it, matching to different Routes for the purposes of applying different plugins, or routing to different upstream services without breaking the external API by changing the prefix.
Problem
The decision was made to do away with these prefixes, but this poses another issue as removing them entirely would be a breaking change in our external API. We will eventually deprecate them according to our policies, but for now we aim to be able to handle a transition period through Kong.
For example:
We create new routes for /bar
and /baz
. Client requests are still made for /foo/bar
and /foo/baz
since they expect those to still work. A Kong plugin should strip /foo
and then trigger a re-route based on the remaining path segment. The remaining /bar
may still go to the foobar
microservice, but /baz
might have additional plugins applied, or route to a new foobaz
microservice instead, and this cannot be allowed to be bypassed by clients still using the /foo
prefix. External requests to /bar
and /baz
directly will skip the rerouting.
In a test implementation of this plugin, I have tried to do this using the ngx.req.set_uri
function, with the jump
argument set to true. As such this was done in the rewrite
handler, and the plugin configured as global. Essentially:
function PathMigrator:rewrite(config)
local matched
local remainder_path
-- Somehow set matched true/false based on whether or not a prefix was matched, and set remainder_path to the rest of the path without the prefix
if matched then
ngx.req.set_uri(remainder_path, true)
end
end
Unexpectedly, when this jump happens we do see (via logging) that the plugin re-triggers to handle the modified path but after plugin execution Kong still routes according to the original request path /foo/bar
resulting in the “no Route matched with those values” 404 response.
Alternate options considered
- Issue HTTP redirects to
remainder_path
- This would be my ideal approach but I am told that we may not be able to rely on our external clients to follow redirects
- Create prefix-matching Routes with
strip-path
that route back to Kong and then Kong can handle the remainder as a new request- Puts double connection load on Kong
Given all this:
Is there any way to trigger a re-route like we are trying to do?
If not, are there any options other than those listed above that we should consider?