Search code examples
nginxluaopenrestyluajit

"API disabled in the current context" error in OpenResty


I'm getting an error, "API disabled in the current context," when I use a Lua library, lua-resty-radixtree in OpenResty:

ERROR: /usr/local/openresty/luajit/share/lua/5.1/resty/expr/v1.lua:319: API disabled in the current context
stack traceback:
        /usr/local/openresty/lualib/resty/core/var.lua:103: in function '__index'
        /usr/local/openresty/luajit/share/lua/5.1/resty/expr/v1.lua:319: in function 'eval'
        ...local/openresty/luajit/share/lua/5.1/resty/radixtree.lua:579: in function 'match_route_opts'
        ...local/openresty/luajit/share/lua/5.1/resty/radixtree.lua:642: in function 'match_route'
        ...local/openresty/luajit/share/lua/5.1/resty/radixtree.lua:675: in function 'match'
        lua/hello.lua:30: in function 'file_gen'
        init_worker_by_lua:45: in function <init_worker_by_lua:43>
        [C]: in function 'xpcall'
        init_worker_by_lua:52: in function <init_worker_by_lua:50>

Here is my nginx.conf file:

pid logs/nginx.pid;
worker_processes  1;
events {
  worker_connections 1024;
}

http {
  server {
    listen 8080;
    location / {
      content_by_lua_file lua/hello.lua;
      }
    }
  }

And the hello.lua file referenced in the Nginx configuration:

ngx.say("Hello user!")

local radix = require("resty.radixtree")
local rx = radix.new({
    {
        paths = { "/aa", "/bb*", "/name/:name/*other" },
        hosts = { "*.bar.com", "foo.com" },
        methods = { "GET", "POST", "PUT" },
        remote_addrs = { "127.0.0.1", "192.168.0.0/16",
            "::1", "fe80::/32" },
        vars = {
            { "arg_name",   "==", "json" },
            { "arg_weight", ">",  10 },
        },
        filter_fun = function(vars, opts)
            return vars["arg_name"] == "json"
        end,

        metadata = "metadata /bb",
    }
})

-- try to match
local opts = {
    host = "foo.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
}
ngx.say(rx:match("/aa", opts))

-- try to match and store the cached value
local opts = {
    host = "foo.com",
    method = "GET",
    remote_addr = "127.0.0.1",
    vars = ngx.var,
    matched = {}
}
ngx.say(rx:match("/name/json/foo/bar/gloo", opts))
ngx.say("name: ", opts.matched.name, " other: ", opts.matched.other)

I installed the library through LuaRocks prior to this after realizing that installing it through OPM would not work because it only supports pure Lua libraries.

Any idea what the issue could be?


Solution

  • The issue is because the Nginx variables in the Lua code cannot be written into in the content_by_lua_ context unless they are already defined.

    To fix this issue, you can define the variables first as shown:

    pid logs/nginx.pid;
    worker_processes  1;
    events {
      worker_connections 1024;
    }
    
    http {
      server {
        listen 8080;
        location / {
          set $arg_name 'json';
          set $arg_weight 100; 
          content_by_lua_file lua/hello.lua;
          }
        }
      }
    

    set_ is executed in the rewrite phase before content_ is executed in the content phase. Once the variables are defined in the rewrite phase, they can be modified in the content phase.

    More information regarding these can be found in the docs: ngx.var.VARIABLE.