#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