#lua 三种重定向的使用及比较
语法:ngx.exec(uri, args?)
主要实现的是内部的重定向,等价于下面的rewrite指令:
rewrite regrex replacement last;
例子:
ngx.exec('/some-location');
ngx.exec('/some-location', 'a=3&b=5&c=6');
ngx.exec('/some-location?a=3&b=5', 'c=6');
location /foo {
content_by_lua_block {
ngx.exec("/bar", { a= 4, b="hello world"});
}
}
location /bar {
content_by_lua_block {
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
ngx.say(key.." = "..val)
end
}
}
"GET /foo/file.php?a=hello" 请求将返回hello 而不是goodbye
```
location /foo {
content_by_lua_block {
ngx.exec("@bar", "a=goodbye");
}
}
location @bar {
content_by_lua_block {
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
if key == "a" then
ngx.say(val)
end
end
}
}
```
该方法不会主动返回,因此,强烈建议在调用该方法时,最好显示加上return,如下所示:
return ngx.exec(...)
语法:ngx.redirect(uri, status?)
该方法会给客户端返回一个301/302重定向,具体是301还是302取决于设定的status值。
如果不指定status值,默认是返回302 (ngx.HTTP_MOVED_TEMPORARILY),其等价于下面的rewrite指令:
rewrite ^ /foo? permanent;# nginx config
如果返回301,那么等价于下面的rewrite指令:
rewrite ^ /foo? redirect;# nginx config
该方法不会主动返回,因此,强烈建议在调用该方法时,最好显示加上return,如下所示:
return ngx.redirect('/foo?a=3&b=4')
语法: res= ngx.location.capture(uri, options?)
用于发出一个同步的,非阻塞的Nginx subrequest(子请求)。
Nginx 子请求可以向其它location发出非阻塞的内部请求,这些location可以是配置用于读取文件夹的,也可以是其它的C模块,比如ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle甚至是ngx_lua自己。
Subrequest只是模拟Http接口,并没有额外的Http或者Tcp传输开销,它在C层次上运行,非常高效。Subrequest不同于Http 301/302重定向,以及外部重定向(通过ngx.redirect)和内部重定向(通过ngx.exec)。
下面是一个基本的例子:
res = ngx.location.capture(uri)
返回一个LUA的TABLE,四个值(res.status, res.header, res.body, and res.truncated)。
res.header包含了所有的子请求的头的信息,它是一个普通的LUA TABLE。比如多个值的相应头,他们以数组的形式按照顺序返回出现。例如:子请求包含了如下信息:
Set-Cookie: a=3
Set-Cookie: foo=bar
Set-Cookie: baz=blah
如上,res.header[“Set-Cookie”] = {“a=3”, “foo=bar”, “baz=blah”}
URI也可以链接自己,例如:
res = ngx.location.capture('/foo/bar?a=3&b=4')
需要注意的是命名的locations,比如@foo在nginx core是不被允许的。
capture函数的第二个参数是可选的,详细说明如下
method: 请求方式,比如ngx.HTTP_POST
body: 子请求的内容
args: 参数
ctx: 特殊的ngx.ctx变量,可以被当前请求赋值,也可以在子请求使用,父子请求共享的变量
vars:
copy_all_vars:
share_all_vars:
POST事例:
res = ngx.location.capture(
'/foo/bar',
{ method = ngx.HTTP_POST, body = 'hello, world' }
)
args事例:
ngx.location.capture('/foo?a=1',
{ args = { b = 3, c = ':' } }
)
copy_all_vars: 顾名思义,就是拷贝父请求的变量到子请求,当子请求变量修改的时候不影响到父请求.
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ copy_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
}
请求 /lua, 则返回:
/other dog: hello world
/lua: hello
share_all_vars: 控制着当前请求是否与子请求分享变量,默认情况是false。如果分享,在子请求修改变量,父请求的变量也随着修改,默认情况下是关闭状态。
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ share_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
}
请求 /lua ,则返回:
/other dog: hello world
/lua: hello world
文章参考:
http://blog.csdn.net/chosen0ne/article/details/7304192
https://github.com/openresty/lua-nginx-module#ngxlocationcapture