nginxluanginx-reverse-proxyopenresty

Dynamic Nginx upstream based on ngx.var set in access_by_lua_block


Simplified NGINX sample config snippet:

http {
  set $foo default;
  access_by_lua_block {
    ngx.var.foo = "bar"
  }

  server {
    listen 8080 default_server;
    server_name localhost;

    location / {
      set $proxy one;
      if ($foo = "bar") {
        set $proxy two;
      }
      proxy_pass http://$proxy;
    }
  }
}

The problem I am seeing is that $foo doesn't seem to be set within the location block. If I add an access log that logs $foo under http the value will be bar. If I put the access log within the location block, then it is default.

How can I dynamically switch upstreams based on the value of an ngx.var set within an access_by_lua_block?


Solution

  • The if statements in the location block appear to execute at a NGINX phase that happens before access_by_lua_block. The fix I came up with was moving the check into access_by_lua_block. proxy_pass executes in the content phase and can read variables set in the access phase.

    http {
      set $proxy one;
      access_by_lua_block {
        ngx.var.foo = "bar"
        if ngx.var.foo == "bar" then
          ngx.var.proxy = "two"
        end
      }
    
      server {
        listen 8080 default_server;
        server_name localhost;
    
        location / {
          proxy_pass http://$proxy;
        }
      }
    }
    

    This is a really contrived example that doesn't make much sense as is, but in the real problem I wasn't simply setting ngx.var.foo = "bar" but instead foo was set based on the result of a response received from a request made within the access block, so it was much more dynamic in nature.