Nginx Lua 三种重定向的使用及比较

#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

posted @ 2020-05-21 15:26  ShengLeQi  阅读(3809)  评论(0编辑  收藏  举报