在nginx中,有两种方式添加自定义的变量:

  • 在配置文件中用set指定添加
  • 在自己编写的C模块中,调用ngx_http_add_variable接口来添加变量

第一种方法较简单,第二种方法有一处需要说明一下。

当调用ngx_http_add_variable接口时,如果传入的flag参数中NGX_HTTP_VAR_NOHASH位被设置了,那么在lua代码中使用ngx.var.XXX是不能访问到该变量的,得到的值是nil。

在这种情况下,如果现在配置文件中通过set指定一个中间变量,则在lua代码中可以访问到。

例如,某个C模块中用带有NGX_HTTP_VAR_NOHASH位的flag参数调用了ngx_http_add_variable,创建了变量A,则如果在lua代码中通过ngx.var.A只能得到一个nil值。

而如果在配置文件中,先调用set命令:set $B $A;,那么在lua代码中,通过代码local A2 = ngx.var.B则可以间接访问到该变量。

翻了一下邮件列表,发现该问题agentzh早有解答:
>逆雪寒:
>通过 ngx.var.fastcgi_script_name 是nil 。 但 set $fsn $fastcgi_script_name 然后 ngx.var.fsn 就能正常获取了。bug ? 还是我理解问题.

agenzh:

这是 Nginx 标准的 ngx_fastcgi 模块的一个限制。$fastcgi_script_name 这个内建变量是这个 ngx_fastcgi 模块定义的,而且在定义时设置了 NGX_HTTP_VAR_NOHASH 这个标志位,从而阻止了 Perl、Lua等各种脚本语言在请求时按变量名动态获取这个变量的值。

之所以你使用 set 指令进行过渡就可以工作是因为 set 指令定位 $fastcgi_script_name 这个变量是在配置加载时,而不是请求时。

你可以自己修改 Nginx 源码树中的 src/http/modules/ngx_http_fastcgi_module.c 这个文件,从ngx_http_fastcgi_vars 这个全局数组的初始化定义中把 NGX_HTTP_VAR_NOHASH 这个标志去除。

从 ngx_lua 模块的角度,是没办法绕过 Nginx 核心中的这个限制的。关于类似这样的问题,可以参见下面这个讨论:

http://forum.nginx.org/read.php?29,239402,239402,quote=1