Replace current upstream host on plugin

Hi, on newer version of Kong what’s the correct way to replace the upstream host (not URI) on the plugin?

On 0.9.x we can assign ngx.ctx.upstream_url. However now replacing host inside ngx.ctx.router_matches or ngx.var.upstream_host doesn’t work.

Hi,

This changed in Kong 0.10 with the introduction of the load balancer. Setting ngx.var.upstream_host in the access phase of a plugin should work, since it is considered right before the load balancing phase, see:

Of course, for this to work, any potential custom Nginx template must have been updated to include the $upstream_host variable, see: https://github.com/Kong/kong/blob/master/kong/templates/nginx_kong.lua#L125

If this does not work for you, could you be more specific, and give us:

  • The version of Kong on which you are seeing this behaviour
  • A more detailed description of what your plugin does, and where (or ideally, if you can, the relevant snippet of code)
  • An example request, along with the Service/Route configuration - this would help us understanding any other issue that may occur, such as your plugin not executing for example…

BTW, in Kong 0.14.0 (of which we just released the first RC), we introduced a Plugin Development Kit, which offers formalized, documented, and forward-compatible Lua functions to do this kind of things (setting/retrieving headers, etc…). You can read more about it in the 0.14.0 Changelog, and expect detailed documentation very soon.

Thank you for the response @thibaultcha ! i learn some new stuff there :slight_smile:

i added ngx.var.upstream_host = "example.com" in my plugin but still doesn’t work.

  • Kong version is 0.12.3
  • This working working fine in production with Kong version 0.9.9
  • i can’t put all code here but here the glimpse
API
        {
            "created_at": 1528434245117,
            "strip_uri": false,
            "id": "b596b1e4-62ca-45e6-b6f2-c3afe412acd7",
            "name": "api-v2-charge",
            "http_if_terminated": false,
            "https_only": false,
            "upstream_url": "https://internal-host-a:8080",
            "uris": [
                "/v2/charge"
            ],
            "preserve_host": false,
            "upstream_connect_timeout": 60000,
            "upstream_read_timeout": 60000,
            "upstream_send_timeout": 60000,
            "retries": 5
        }

Plugin will read request boy POST-ed to that API, and if the condition meet it will change upstream to https://internal-host-b:8080. What it does basically (on access block)

ngx.req.read_body()
if cond(ngx.req.get_body_data()) then
  ngx.log(ngx.INFO, "true")
  ngx.var.upstream_host = "internal-host-b:8080"
end

On test it always goes to internal-host-a. no problem in the cond() since the log prints.

Please inquire if there’s anything more you need.