W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在 Nginx 的典型應(yīng)用場(chǎng)景中,幾乎都是只讀取 HTTP 頭即可,例如負(fù)載均衡、正反向代理等場(chǎng)景。但是對(duì)于 API Server 或者 Web Application ,對(duì) body 可以說(shuō)就比較敏感了。由于 OpenResty 基于 Nginx ,所以天然的對(duì)請(qǐng)求 body 的讀取細(xì)節(jié)與其他成熟 Web 框架有些不同。
我們先來(lái)構(gòu)造最簡(jiǎn)單的一個(gè)請(qǐng)求,POST 一個(gè)名字給服務(wù)端,服務(wù)端應(yīng)答一個(gè) “Hello ****”。
http {
server {
listen 80;
location /test {
content_by_lua_block {
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
}
}
測(cè)試結(jié)果:
? ~ curl 127.0.0.1/test -d jack
hello nil
大家可以看到 data 部分獲取為空,如果你熟悉其他 web 開(kāi)發(fā)框架,估計(jì)立刻就覺(jué)得 OpenResty 弱爆了。查閱一下官方 wiki 我們很快知道,原來(lái)我們還需要添加指令 lua_need_request_body 。究其原因,主要是 Nginx 誕生之初主要是為了解決負(fù)載均衡情況,而這種情況,是不需要讀取 body 就可以決定負(fù)載策略的,所以這個(gè)點(diǎn)對(duì)于 API Server 和 Web Application 開(kāi)發(fā)的同學(xué)有點(diǎn)怪。
參看下面例子:
http {
server {
listen 80;
# 默認(rèn)讀取 body
lua_need_request_body on;
location /test {
content_by_lua_block {
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
}
}
再次測(cè)試,符合我們預(yù)期:
? ~ curl 127.0.0.1/test -d jack
hello jack
如果你只是某個(gè)接口需要讀取 body(并非全局行為),那么這時(shí)候也可以顯示調(diào)用 ngx.req.read_body() 接口,參看下面示例:
http {
server {
listen 80;
location /test {
content_by_lua_block {
ngx.req.read_body()
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
}
}
ngx.req.get_body_data() 讀請(qǐng)求體,會(huì)偶爾出現(xiàn)讀取不到直接返回 nil 的情況。
如果請(qǐng)求體尚未被讀取,請(qǐng)先調(diào)用 ngx.req.read_body (或打開(kāi) lua_need_request_body 選項(xiàng)強(qiáng)制本模塊讀取請(qǐng)求體,此方法不推薦)。
如果請(qǐng)求體已經(jīng)被存入臨時(shí)文件,請(qǐng)使用 ngx.req.get_body_file 函數(shù)代替。
如需要強(qiáng)制在內(nèi)存中保存請(qǐng)求體,請(qǐng)?jiān)O(shè)置 client_body_buffer_size 和 client_max_body_size 為同樣大小。
參考下面代碼:
http {
server {
listen 80;
# 強(qiáng)制請(qǐng)求 body 到臨時(shí)文件中(僅僅為了演示)
client_body_in_file_only on;
location /test {
content_by_lua_block {
function getFile(file_name)
local f = assert(io.open(file_name, 'r'))
local string = f:read("*all")
f:close()
return string
end
ngx.req.read_body()
local data = ngx.req.get_body_data()
if nil == data then
local file_name = ngx.req.get_body_file()
ngx.say(">> temp file: ", file_name)
if file_name then
data = getFile(file_name)
end
end
ngx.say("hello ", data)
}
}
}
}
測(cè)試結(jié)果:
? ~ curl 127.0.0.1/test -d jack
>> temp file: /Users/rain/Downloads/nginx/client_body_temp/0000000018
hello jack
由于 Nginx 是為了解決負(fù)載均衡場(chǎng)景誕生的,所以它默認(rèn)是不讀取 body 的行為,會(huì)對(duì) API Server 和 Web Application 場(chǎng)景造成一些影響。根據(jù)需要正確讀取、丟棄 body 對(duì) OpenResty 開(kāi)發(fā)是至關(guān)重要的。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: