-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[request] support for routing based on path? #192
Comments
+1 simply for the cost of ssl certs |
Great idea! I've added a request label, maybe @thefosk or @thibaultcha could chime in on the implementation details as I don't think this is something that could be added as a plugin since the routing is handled by the Kong core. |
This is a feature I have been thinking for a while, and I really like the idea. Will draft out a simple implementation. |
proxy is a good aproach i guess we can have them standalone next to each other like api1.example.com and after that we setup a new subdomain and add the "api id" + a location folder not sure if its that trivial but that would not change the way the actual routing works instead it acts as a compliment layer just my 2 cents here .. please ignore if im beeing missleading with a simplistic aproach |
👍 I've been thinking of this feature for making an abstraction layer between consumer and internal API. |
Glad to hear that you guys think it is a useful feature. Another thing to keep in mind is that this would also likely be used for micro-services and splitting up functionality. So keeping with my previous example and just focusing on if I noticed that my login functionality was taking lots of hits and causing me to scale even though the rest of my end-points weren't experiencing much load I would split this up to do something like the following. The path I think this comes down to just the fact that order or specificity matters. I think order (where first match is the one that matters) is the more common approach due to it being simpler to implement. So in my example the order of my APIs would be something like this:
|
I like the idea 👍 Your latest example (with an order of priority to define the routing) is something that we are used to see in code, but I am curious as to what it would look like when configuring it with simple API calls... A priority value maybe? |
As I've been going through trying out other API gateways I thought Tyk had some easy to understand options that were useful even in my simple testing. For the configuration of their Proxy piece they have a few simple options which I think would serve as a good starting point.
|
@thibaultcha Yeah, it's a weird one when dealing with an API. You obviously don't want to go by creation date, or update the entire set of APIs. The way that AWS does it for things like Network ACLs which I think is simple is that they have you put in a kind of
I think it clearly shows the order (you would just need to make sure |
On an other note, maybe the resolvers too could be plugins. We call the current resolver (by Btw, it is worth noting that this is also close to how NGINX natively supports proxying, even if less flexible than what you are describing @DavidTPate:
|
I was thinking about such a rule @DavidTPate. Here the interval between two routes is huge but to be 100% future proof, if one decides to insert a route at a value that already exists we could also "push" all values after the one being inserted. I don't see another solution right now than this, but it seems decent. An UI can easily and nicely deal with this on top of the admin API. |
I really like this idea. We at QuizUp developed our own nginx based routing solution where we route based on the request path (location). Additionally, something I would be very interested in seeing (and potentially developing in this project) is support for registering backend nodes directly with Kong. This is to avoid having to rely on (potentially stale) DNS records for discovering backends. Having a complete list of backends (internal IPs usually) per microservice would also allow for more sophisticated load balancing algorithms to be employed (I am thinking least connection, and since there is the possibility of sharing state via cassandra, this makes a lot of sense to me!). Awesome project btw :-) |
Absolutely similar. The #157 issue seems quite focused on how nginx does this, but I assume we could do this in two ways. *1. Deltas (ie. add/rem particular backend/upstream from an api):
or
*2. Complete overwriting of upstreams (basically a "set" operation):
Or whatever makes most sense. I just came across your project and immediately decided to start suggesting stuff -- but in my defence, if you guys like the ideas I wouldn't mind contributing :-) |
👍 We are using a home-built nginx routing to different upstreams based on the request path in the API. We replace the proxy_pass using a variable after matching the path pattern in a regex. This will also help in having endpoint level rate limiting/throttling. Would love to have this in kong. Will make our migration to kong much easier! |
+1 |
1 similar comment
+1 |
+1 Here's a real example of where I do routing based on endpoints in nginx:
|
Before implementing this, a quick follow-up to see what we think about it. We currently have a resolver that we can call the "host resolver". I shall refer to the resolver described by @DavidTPate as the "path resolver". On the usability side:It would be nice to be able to configure an API wether its routing should happen by host or by path. Say the API now has 2 properties:
My 2 cents: separate those resolvers but keep them bundled into the core. Have an API use one or the other depending on which property is set. Refuse an API that uses both. On the implementation side:A nice solution would be to now separate the properties used by the resolvers and the APIs:
@thefosk @montanaflynn thoughts? |
That sounds like a good solution to me. I could see someone attempting to use both a "host resolver" and a "path resolver" but to me that screams of poor API design and I'm honestly not sure if even Nginx has the ability to do both (without duplication of configuration). |
@thibaultcha I would say to allow for both with only one or the other being required. This way you can set up multiple APIs in one Kong install and still handle all the above use cases that @DavidTPate described. The ordering for how Kong would pick which one could be like this:
There's a good answer on stackoverflow about how nginx handles prioritizing paths. Here's a bigger snippet of the nginx config I put above showing how I'm matching by host & path. Two paths are the same but lead to different outcomes dependent on the host. You'll also notice that I'm using regex in the path which is something that we should consider as well.
|
@montanaflynn I agree with this. |
+1 |
1 similar comment
+1 |
this feature would be a requirement for us to adopt kong. (+1) |
I just would like to tell that this feature is coming in the |
@thefosk Thanks for the quick response 👍 |
🎉 |
There are a lot of things we need to figure out before implementing this. Requirements
Schema 1Considering this, and the way we want to query Cassandra, all that by keeping our RESTful configuration capabilities, this is a potential model (and the most valid I could think of): CREATE TABLE apis(
id uuid,
name text,
PRIMARY KEY(id)
);
CREATE TABLE hosts(
id uuid,
api_id uuid, -- foreign to apis.id
public_dns text,
target_url text,
PRIMARY KEY(id)
);
CREATE TABLE paths(
id uuid,
api_id uuid, -- foreign to apis.id
host_id uuid, -- useful to require this Path to first match a Host (rule 3)
listen_path text,
priority int,
target_url text,
PRIMARY KEY(id, priority) -- priority allows us to ORDER BY a query, but I would probably rather do that in the application level
);
CREATE INDEX ON hosts(public_dns);
CREATE INDEX ON paths(listen_path); This schema allows us to follow the requirements:
The problems here are:
Proposed workarounds
Schema 2I also considered such a schema: CREATE TYPE path(
listen_path text,
priority int,
host text,
target_url text
);
CREATE TYPE host(
public_dns text,
target_url text
);
CREATE TABLE apis(
id uuid,
name text,
host host, -- one Host
paths frozen<set<path>>, -- multiple Paths
PRIMARY KEY(id)
); But it arises more concerning problems:
From here, I see 2 solutions:
MigrationsFinally, another problem to consider is that almost any schema change will require a heavy migration. By heavy I mean moving data around, possibly by providing a script or something to migrate from the current
or
All that should be done with users doing a backup of their data first. Kong is not 1.0 yet so I don't see handling that as a priority. Users should expect having to reconfigure their APIs if they want to upgrade. |
I have some feedback and questions.
SELECT id FROM apis WHERE public_dns = ? OR listen_path = ?; or (if possible in Cassandra): SELECT id FROM apis WHERE public_dns CONTAINS ? OR listen_path CONTAINS ?; Not sure if there is any limitation with Cassandra if we do this.
|
Yeah I thought about it, but it brings a lot of configurations headaches, because one could have 2 hosts, 2 paths that only validates if Path A + Host A, and Path B + Host B, but it can be extremely confusing very fast. But having 1 Host and X Paths, we respect the nginx behaviour as showed in the examples in this thread. I think it does more harm than anything.
See my point about supporting it: it means everything will have to be in memory and the routing will be O(n), because we need to compare a path against every configured Path. Also your example is a Host? Even if we support 1 Host per API, same, we would need to have every Host in memory too. (See the conclusion about that)
Cassandra does not have support for such an
If we drop this we absolutely cannot have multiple Paths per API like @DavidTPate described it ( Our problems are:
To conclude, if we want to stick with those requirements, and fix 1, 2, 3, 4, I think we have no choice but to load the Host(s) (plural if we decide to support many Hosts, but that brings configuration concerns as mentioned) and Paths in memory. And somehow reload them when they get modified. After all, it is what nginx is doing too, except you don't expect a configuration file to have tens of APIs, where you can expect Kong to have such a number. Schema 2 or equivalent would be valid in that case. |
Keep one host for this version. Simpler. |
Just brainstorming here, but another options would be having only one property called CREATE TABLE IF NOT EXISTS apis(
id uuid,
name text,
matchers set<text>,
target_url text,
created_at timestamp,
PRIMARY KEY (id)
); We could support multiple DNS and multiple paths in one field: SELECT * FROM apis WHERE matchers CONTAINS 'something.com' ALLOW FILTERING; or SELECT * FROM apis WHERE matchers CONTAINS '/hello/world' ALLOW FILTERING; This won't fix the two-queries problem because I think Cassandra doesn't support SELECT statements to search for multiple values in a field (I might be wrong): SELECT * FROM apis WHERE matchers IN ('something.com', '/hello/world') ALLOW FILTERING; |
First implementation drafted in #282. It only supports 1 path per API. Since supporting all the requested features means a lot of rewritten code, I opted for breaking down the implementation in 2 parts:
|
Closing this and adding support for multiple path/multiple hosts in one of the upcoming releases. Thank you all! |
Hi there! Been messing with this a little bit as I'm vetting API gateways to use. I really like the idea of the project but I'm running into an issue where my main routing to services is done based upon path instead of Host.
Was wondering if I'm just overlooking the feature or if there has been any talk of the addition of such functionality. Details below.
If for example I had 3 services that I was running (let's call them
auth
,pizza
, andtacos
).As best as I understand it Kong is setup to handle this where each of these services might be available internally at:
auth.internaldomain.com
,pizza.internaldomain.com
,tacos.internaldomain.com
and the routing is done based upon someone's intention to go toauth.externaldomain.com
,pizza.externaldomain.com
, ortacos.externaldomain.com
.Instead my setup deals with routing to services based upon a part of the path. So, the equivalent calls would be made to
api.externaldomain.com/auth
,api.externaldomain.com/pizza
, orapi.externaldomain.com/tacos
.From looking through the docs this didn't seem like a feature that currently exists, love to hear your thoughts on it.
The text was updated successfully, but these errors were encountered: