Skip to content
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] Allow mapping arbitrary request headers to upstream targets #403

Closed
montanaflynn opened this issue Jul 15, 2015 · 18 comments
Closed

Comments

@montanaflynn
Copy link

I would like to use Kong as a reverse proxy without the need to change the host header. Essentially I want Kong to use an arbitrary header of my choosing to "map" the request to the appropriate upstream target.

Say this was implemented and I added the API http://api.example.com/weather to Kong with the header to look for called service then I would be able to make the request:

curl http://kong:8000?location=USA -H "service: weather"

which would map to the upstream target http://api.example.com/weather

I think this may be related to #203 except it let's the user choose the header to replace host with at the time of creating the API.

@thibaultcha thibaultcha changed the title Allow mapping arbitrary request headers to upstream targets [request] Allow mapping arbitrary request headers to upstream targets Jul 15, 2015
@haifengkao
Copy link

"let's the user choose the header to replace host" is done in https://github.com/haifengkao/kong_proxy
It still lacks a lot of forward proxy features. Feel free to send pull requests.

@mv2a
Copy link

mv2a commented Jan 15, 2018

+1
The problem I am facing is that I need to route the requests from legacy clients and I can't just force them to include the 'host' header that is required by Kong. These old clients will send some specific headers that we have no control of and that's how we identify them to be part of the legacy stack.

@mv2a
Copy link

mv2a commented Jan 15, 2018

It is really a shame that the routing is handled by Kong's core. I suppose the addition of a plugin that exposes an arbitrary header to drive the routing would not be possible then. @haifengkao nice work though but I would endup with unsupported code that I would have to maintain myself.

@thibaultcha
Copy link
Member

@mv2a Why not? It is definitely possible and already done in various production setups.

@aehlke
Copy link

aehlke commented Jan 19, 2018

@thibaultcha could you please point us to some example of this? Also interested in implementing custom routing logic.

To elaborate on my use case: we'd like to do custom canary releases, since we have requirements that are incompatible with the weighted canary rollout that Kong supports out-of-box. (We're used by university professors - we need to keep a prof and their class of students in the same backend version, so we want to incrementally rollout by groups of users rather than a selection of traffic. We can do this by inspecting a header, if we have some way to extend Kong with this logic.)

@mv2a
Copy link

mv2a commented Jan 19, 2018

yeap, me too. Can you give us an example of a custom routing logic implementation that doesn't touch Kong's core?

@taotao2014
Copy link

Solution?

@thibaultcha
Copy link
Member

Hey all,

Yes, gladly! Disclaimer: as of today, it does require a little bit of tinkering considering the API behind custom routing (from plugins) is not stable and hence, not public (nor officially documented). One could find out about it by browsing the source code (not ideal), and we also point out users to it when they ask about it. We do have plans to make this API stable and user-friendly (as in, Lua function to call for custom request rewriting) and documented.

Now, onto the relevant bits.

One of the most recent mentions of this API is in this Kong Nation message, which details the relevant variable to update the upstream URL, as well as some state exposed to plugins with regards to how a request was matched. The later is particularly relevant since it provides information to the plugin such as the host of the matched API (particularly relevant if it is set to a wildcard, like *.foo.com, which would match a Host header such as bar.foo.com. It also exposes URI regex capture groups, for URIs such as /users/(?<id>\d+)/profile, where ngx.ctx.uri_captures.id would be set). For changing other parts of the request, Kong ensures to integrate properly with the ngx_lua API, so refer to the ngx_lua documentation for this. All updates must be done in the access phase of a plugin, for obvious reasons.

To sum it up the various parts of the request you can change before a request is proxied upstream:

  • upstream scheme: ngx.var.upstream_scheme
  • URL: ngx.var.upstream_uri
  • querystring: ngx_lua's ngx.req.set_uri_args()
  • Host header: ngx.var.upstream_host
  • Other headers: ngx.req.set_header()
  • Body: ngx.req.set_body_data() or other similar APIs
  • TLS SNI: ngx.var.upstream_host as well

Once this logic is implemented in a plugin, said plugin must also be executed during a request. Either configure the plugin as a global plugin, or configure it on a particular API object. The plugin then kicks in and overwrites the values set by Kong Core and redirects the request elsewhere.

There are a lot of possibilities, pretty much everything that Kong does can be done in a plugin (even advanced load balancing, retries, etc...). The upcoming Lua API for such custom routing plugins will also expose Kong's circuit-breaker API, which can provide period healthchecks, healthy/unhealthy state of upstreams, etc... It will be easier to use once all of this gets formalized into a proper, documented API.

@thibaultcha
Copy link
Member

Oh, and reading headers from a plugin is the usual ngx.req.get_headers() or ngx.var.http_[header_name].

@iambowen
Copy link

I think it's a necessary function to make api take custom header to decide to choose which upstream. Oftentimes, services are more likely to put stuff in cookies/headers instead in the requested url.

@aehlke
Copy link

aehlke commented Apr 27, 2018

Now that it’s been a few months, have there been any changes in Kong to make this easier (such as making the private methods above public)? Does anyone have experiences with this they can share?

@thibaultcha
Copy link
Member

@aehlke We are actively working on what we call a Plugins SDK that formalizes a set of Lua functions to do this from plugins. Stay tuned, we should have updates in the next few weeks.

@aehlke
Copy link

aehlke commented Sep 18, 2018

@thibaultcha thanks for the update back then; I'm not sure I can find the "Plugins SDK" now, did it end up being introduced?

@coopr
Copy link
Contributor

coopr commented Sep 18, 2018

"Plugins SDK" became the Plugin Development Kit (PDK) - lots of info here https://docs.konghq.com/0.14.x/pdk/

@thibaultcha
Copy link
Member

@aehlke Sorry for not following up here! Yes, thank you @coopr, as you said, the Plugins SDK became the Plugin Development Kit when it was released in 0.14.0.

It commodities operations that I described in my earlier reply, such as interacting with the downstream and upstream requests/responses. E.g. updating the URL in the upstream request, or grabbing the host header from the client’s request, etc... It also comes with other commodities for various common operations done by the gateway, which is useful for developers not entirely familiar with Lua.
Please check it out, and let us know how we can improve it :)

@aehlke
Copy link

aehlke commented Sep 25, 2018

Thanks very much! We will be using this to control canary rollout based on user segments. We are a few months away from starting this so will try to follow up again with feedback.

@hishamhm
Copy link
Contributor

Support for routing by arbitrary headers has been merged in Kong next and will be available in the next release!

@thibaultcha
Copy link
Member

PR for reference: #4758

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants