#lua 三种重定向的使用及比较
1. ngx.exec
语法: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');
args参数可以以string的形式给出,也可以以lua table的形式给出,如下所示:
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 } }
如果给定的uri是命名的location,那么可选参数args就会被自动忽略的,如下所示:
"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(...)
2. ngx.redirect
语法: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')
3. ngx.location.capture
语法: 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
原文链接:https://blog.csdn.net/liwf616/java/article/details/78256062