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


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

相关内容

    暂无相关文章