一 ngx.arg
arg api 只包含一个接口 ngx.arg,ngx.arg 可以在两个阶段使用:set_by_lua 和 body_filter_by_lua。
1. 在 set_by_lua 中使用
在 set_by_lua 阶段 ngx.arg 是一个只读表,保存指令的输入参数。
| 1 | location /foo { | 
这是 lua-nginx-module 中的一段示例,在 set_by_lua 指令中通过 ngx.arg[1] 获得 $a 变量,ngx.arg[2] 获得 $b 变量,ngx.arg[3] 获得 $c 变量。
2. 在 body_filter_by_lua 中使用
当在 body_filter_by_lua 阶段使用 ngx.arg 表时,ngx.arg[1] 持有调用 lua-nginx 模块 body_filter 函数传入的数据块,ngx.arg[2] 用来标记整个输出流是否结束(布尔类型)。在 body_filter_by_lua 阶段,ngx.arg 是可以修改的,ngx.arg[1] 设置为 nil 或者 "" 后续的 body_filter 将不会收的数据块。同时还可以修改 ngx.arg[2] 控制下游 body_filter 是否已经发送完毕。在 body_filter_by_lua 中只能使用 1 和 2 两个索引。
二 实现
ngx.arg 是 table 类型数据,在 lua-nginx 中通过设置其 __index 和 __newindex 方法来实现获得参数、包体、设置包体和 eof 状态的功能。注册 ngx.arg 函数:
| 1 | static void | 
__index 方法同时支持 set_by_lua 和 body_filter_by_lua 功能,用来获取参数、应答包体、应答包体 eof 状态。__newindex 方法仅支持 body_filter_by_lua 阶段,用来设置应答包体、应答包体 eof 状态。
1.  set_by_lua 参数获取
在 set_by_lua 中参数的获取最终实现函数是 ngx_http_lua_setby_param_get。在使用 ngx.arg[idx] 进行获取参数时所有参数以及保存在数组中,通过 ngx_http_lua_args_key 伪索引获得数组。因为在 C 中索引从 0 开始,因此传入的索引 idx 需要进行减一操作。
| 1 | int | 
2. body_filter_by_lua 获取数据
在 body_filter_by_lua 中获取应答包体、应答 eof 状态的实现函数是 ngx_http_lua_body_filter_param_get。函数仅允许使用 1 或 2 作为索引,当索引为 2 时仅需要判断输出链 ngx_chain_t 类型数据是否为空即可返还布尔类型应答值以标识应答是否结束;当索引为 1 时需要遍历输出链,计算长度,并将其拷贝到缓冲区进行返回。
| 1 | // body filter 阶段获取待输出数据 | 
3. body_filter_by_lua 设置数据
在 body_filter_by_lua 中设置应答包体、应答 eof 状态的实现函数是 ngx_http_lua_body_filter_param_set。
| 1 | int | 
在 body_filter_by_lua 中通过 ngx.arg[1] 设置应答包体时可以使用 table 作为值,但是 table 必须是数组类型,非哈希表。
