Nginx 子請求是一種非常強有力的方式洽洁,它可以發(fā)起非阻塞的內(nèi)部請求訪問目標 location。目標 location 可以是配置文件中其他文件目錄菲嘴,或任何其他 nginx C 模塊饿自,需要注意的是碎浇,子請求只是模擬 HTTP 接口的形式,沒有額外的 HTTP/TCP 流量璃俗,也沒有IPC (進程間通信) 調(diào)用奴璃。所有工作在內(nèi)部高效地在 C 語言級別完成泉唁。
原型:
local res = ngx.location.capture(uri)
返回一個包含四個元素的 Lua 表 (res.status,res.header,res.body, 和res.truncated)甜癞。
res.status(狀態(tài)) 保存子請求的響應(yīng)狀態(tài)碼。
res.header(頭) 用一個標準 Lua 表儲子請求響應(yīng)的所有頭信息稿黄。如果是“多值”響應(yīng)頭唱星,這些值將使用 Lua (數(shù)組) 表順序存儲雳旅。
res.body(體) 保存子請求的響應(yīng)體數(shù)據(jù),它可能被截斷间聊。用戶需要檢測res.truncated(截斷) 布爾值標記來判斷
模擬get請求
local res = ngx.location.capture(
? ? ? ? '/foo?a=1',
? ? ? ? { args = { b = 3, c = 'a' } }
)
等同于
local res = ngx.location.capture('/foo?a=1&b=3&c=a')
foo.lua代碼:
ngx.say("par_1=", ngx.var.b)
ngx.say("par_2=", ngx.var.c)
--do? some things ...
模擬post請求
do.lua代碼:
local res = ngx.location.capture(
? ? ? ? ?'/bar',
? ? ? ? ?{?
? ? ? ? ? ? ? ? ?method = ngx.HTTP_POST,
? ? ? ? ? ? ? ? ?body = 'hello, world'
? ? ? ? ?}
)
bar.lua代碼:
--do? some things ...
模擬post請求發(fā)送json字符串
easy.lua代碼:
local res_userinfo = ngx.location.capture(
? ? ? ? ? '/dd',
? ? ? ? ? {
? ? ? ? ? ? ? ? ?method = ngx.HTTP_POST,
? ? ? ? ? ? ? ? ?body = cjson.encode(?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? time ? = 'time' ,
? ? ? ? ? ? ? ? ? ? ? ? ? ? appid = 'appid' ,
? ? ? ? ? ? ? ? ? ? ? ? ? ? sid ? ? = 'sid' ,
? ? ? ? ? ? ? ? ? ? ? ? ? ? from ?= 'from' , ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ?page ?= 'page'
? ? ? ? ? ? ? ? ? ? ? })
? ? ? ? ? }
)
dd.lua代碼:
ngx.req.read_body()
local json_str = ngx.req.get_body_data()
local arr? ? ? = comm:json_decode(json_str)
ngx.say(arr['sid'])
--do ?some things ...
ngx.location.capture_multi用法差不多
local ?res1, res2, res3=ngx.location.capture_multi{? ?
? ? ? ? {"/foo", { args="a=3&b=4"} },? ?
? ? ? ? {"/bar"},? ??
? ? ? ? {"/baz", { method=ngx.HTTP_POST, body="hello"} }
}
if res1.status == ngx.HTTP_OK
then
? ? ? ?...
end
if res2.body == "BLAH"
then
? ? ? ?...
end
...