Kong: Kong route pathing for wildcard feature w backend service api seems slightly off?

Created on 2 Sep 2020  ·  8Comments  ·  Source: Kong/kong

Summary

I remember reading PRs awhile back on some routing changes but was just going to reiterate a case that seems bugged to me just ootb in behavior

Was looking into a customer report and tried a number of tests, one test that seemed to not behave as I would expect was this Kong proxy setup(I don't even consider the case to be a desired customer call, its quiet invalid for what I think the intent would be, but nonetheless Kong should still proxy it properly for the pathing behavior ootb):

{
  "strip_path": true,
  "path_handling": "v0",
  "paths": [
    "/api/dev/cdm/company/my-service/v1"
  ],
  "destinations": null,
  "headers": null,
  "protocols": [
    "http",
    "https"
  ],
  "methods": null,
  "snis": null,
  "service": {
    "host": "api.company.com",
    "created_at": 1595416528,
    "connect_timeout": 2000,
    "id": "56f7e4eb-abab-453b-94b9-87f28072bb14",
    "protocol": "http",
    "name": "my.service.name",
    "read_timeout": 9000,
    "port": 80,
    "path": "/api/my-service/v1",
    "updated_at": 1597442064,
    "retries": 0,
    "write_timeout": 9000,
    "tags": null,
    "client_certificate": null,
    "extras": {}
  }
}

Now by default I would expect if I called the Kong Proxy URL like:

https://gateway.company.com/api/dev/cdm/company/my-service/v1142032

Where I essentially forgot to put a / in my proxy URL to add division between the version(v1) and some sort of id lookup(142032), that Kong would also route to the service on a path like:
api.company.com/api/my-service/v1142032

But turns out Kong is actually sending the traffic to:

api.company.com/api/my-service/v1/142032

So it added an extra / in there as if the customer had originally called the proxy URL properly like so with / seperation between proxy route version and the id they mean to pass:

https://gateway.company.com/api/dev/cdm/company/my-service/v1/142032

Maybe there is a deeper reason for this behavior out of Kong in design but naturally my inclination would be transparent pathing if client forgets the trailing / between the established proxy route and an id then Kong too will ensure that id gets slapped on the end of that services path element.

I noticed path_handling is set to v0 as well, so maybe that has something to do with it(which has been the Kong standard/default over many versions with the option now for some newer v1 which I will need to study the diffs in behavior at some point).

Steps To Reproduce

  1. Setup a service+route like I mentioned above and test wildcarding behavior

Additional Details & Logs

  • Kong version 2.0.5

All 8 comments

What I think is happening here:

  1. client sends: https://gateway.company.com/api/dev/cdm/company/my-service/v1142032
  2. kong matches that with: /api/dev/cdm/company/my-service/v1
  3. kong strips the prefix so at this point you have: 142032
  4. v0 concatenates /api/my-service/v1 to 142032 and v0 always adds / when it concatenates if there is not already a one, v1 does not as far as I remember

Hmm so the default of Kong is to add / and slap it in after the match. I suppose v0 has always been the case but these customers said they had used the never observe this behavior. Will try to manipulate their non-prod proxy to use v1 path handling and see if it behaves more as expected/desired.

Issue with v1:

v1 never adds slash when concatenating.

Create service, see there is no ending slash at “/anything”:

$ http -f put :8001/services/t1 url=http://httpbin.org/anything

Create route:

$ http -f put :8001/services/t1/routes/r1 paths=/

v1:

$ http :8000/
HTTP/1.1 200 OK (tries to proxy to http://httpbin.org/anything)
$ http :8000/test      
HTTP/1.1 404 NOT FOUND # v1 tries to proxy to /anythingtest (feels unexpected)



md5-56042e8ee63f6f4db87b15665c12c280



$ http :8000/
HTTP/1.1 200 OK (tries to proxy to http://httpbin.org/anything)



md5-2ac29d00b63364ebd8f310fbb31549b1



$ http :8000/test ((tries to proxy to http://httpbin.org/anything/test)
HTTP/1.1 200 OK



md5-36654dbb42cc5c751b5caca485d40659



$ http -f patch :8001/services/t1 path=/anything/
````

*v1:*



md5-d92bbe983dfe5c30f88a7a820f5524ad



$ http :8000/test ((tries to proxy to http://httpbin.org/anything/test)
HTTP/1.1 200 OK

*v0:*

$ http :8000/
HTTP/1.1 404 NOT FOUND # v0 tries to proxy to /anything/ (seems reasonable)


$ http :8000/test ((tries to proxy to http://httpbin.org/anything/test)
HTTP/1.1 200 OK

*Issue with v0 and v1:*

`v0` forcibly adds slash when concatenating.

http -f patch :8001/routes/r1 paths=/anything
http -f patch :8001/services/t1 path=/anything

*v1:*

$ http :8000/anythingelse
HTTP/1.1 404 NOT FOUND # v1 tries to proxy to /anythingelse (feels unexpected)

*v0:*

$ http :8000/anythingelse
HTTP/1.1 200 ok # v0 tries to proxy to /anything/else (seems reasonable)

*See the added “/” at the end of path:*

http -f patch :8001/services/t1 path=/anything/

*v1:*

$ http :8000/anythingelse
HTTP/1.1 200 ok # v1 tries to proxy to /anything/else (feels unexpected(?))

*v0:*

$ http :8000/anythingelse
HTTP/1.1 200 ok # v0 tries to proxy to /anything/else (feels unexpected(?))
```

This is also an issue without stripping if you add service with path “/users-” and route with “/” and request with “/2”, the v0 will proxy to “/users-/2” whereas v1 will proxy to “/users-2”.

In my opinion the v0 is most of the time desired, and v1 is the unexpected one. But people may have different view points. The v1 was invented by accident. We didn't knew it broke v0 behavior, but it did. And then it was too late to remove as it went to 1.0 and we detected it at 1.2. There has been several pr's, e.g. I created path_seprated one at some point, and we played around with multiple others, and finally settled with v0 / v1 and path_handling property.

In short v1 thinks paths as strings while v0 thinks them more as path segments. Both have their share of issues.

Appreciate the feedback, did forward some of this information along. I think we just continue to use v0 as a standard knowing the edgecases.

yes, usually when you have such edge-case, swithcing path_handling on that route might help, or adjusting the service path.

Yeah my original vire that its a client error and where they missed the trailing / after version and before an id in my sample should not be viewed as an actual issue that needs “fixing”, I will consider it one of the times Kong is trying to active help out a bad consumer 😂.

I feel like as a goal Kong should be as transparent in behavior as possible to remove situations like this(in this situation transparency was slightly lost because Kong did add a / and transparent wildcarding would not do so), but behavior at the router layer is tricky to adjust because you could unknowingly screw over a bunch of existing customer use cases even for a situation where the adjustment was warranted. I can live with this one off situation and putting their proxy on v1 when we have 1000s of others on v0 just as a standard doesn’t seem the right move either. I like everything to maintain consistency to reduce surprises.

@jeremyjpj0916,

here is our test matrix for that (some of them might feel slightly off):
https://github.com/Kong/kong/blob/master/spec/fixtures/router_path_handling_tests.lua

Was this page helpful?
0 / 5 - 0 ratings