Hello!
2014-04-30 0:10 GMT-07:00 李阳光:
> 在read_body的使用范围是rewrite_by_lua, access_by_lua*, content_by_lua**,
> 为何没有set_by_lua这个context?
> 是基于什么考虑呢?
引用一下 set_by_lua 的官方文档里对此的说明:
“This directive is implemented by injecting custom commands into the
standard ngx_http_rewrite_module's command list. Because
ngx_http_rewrite_module does not support nonblocking I/O in its
commands, Lua APIs requiring yielding the current Lua "light thread"
cannot work in this directive."
> 我的理解rewrite_by_lua 和set_by_lua应该都是在nginx的rewrite阶段处理,为什么会有这个区别呢?
>
如上面引用的说明,这是 nginx 标准的 ngx_rewrite 模块的功能限制。
> 我现在的应用场景是这样的:
> 需要在set_by_lua中读取body内容,然后设置某些ngx.var的变量,
> 接下来会使用if指令对变量进行判断,是使用proxy_pass或者fastcgi_pass连接上游服务。
>
> 现在的问题在set_by_lua中无法读取body,只能使用rewrite_by_lua或者access_by_lua,
> 其中access_by_lua并不可使用,因为其会在if指令之后运行,这个不符合预期
> 使用rewrite_by_lua + rewrite_by_lua_no_postpone on; 可以保证其在if指令前运行,但是由于需要
> 在lua脚本中更新nginx的变量,而此时set指令并未执行,所以就无法向外部传递变量
>
建议尽量避免使用标准模块 ngx_rewrite 的 if 指令,因为“if is evil”:
http://wiki.nginx.org/IfIsEvil
推荐的玩法是分别为你的 proxy_pass 和 fastcgi_pass 定义专门的"named location",比如
location @proxy {
proxy_pass ...;
}
location @fastcgi {
proxy_pass ...;
}
然后再在 Lua 里按条件发起内部跳转,比如
location / {
content_by_lua '
if some_condition then
return ngx.exec("@proxy")
end
if some_other_condition then
return ngx.exec("@fastcgi")
end
return ngx.exit(404)
';
}
当然,你也可以为一种情况避免内部跳转,即改写成下面的形式:
location / {
rewrite_by_lua '
if some_condition then
return ngx.exec("@proxy")
end
';
fastcgi_pass ...;
}
这样你就可以省去 location @fastcgi 和一次内部跳转了。
Regards,
-agentzh