在 Nginx 的典型應(yīng)用場景中,幾乎都是只讀取 HTTP 頭即可,例如負載均衡、正反向代理等場景。但是對于 API Server 或者 Web Application ,對 body 可以說就比較敏感了。由于 OpenResty 基于 Nginx ,所以天然的對請求 body 的讀取細節(jié)與其他成熟 Web 框架有些不同。
我們先來構(gòu)造最簡單的一個請求,POST 一個名字給服務(wù)端,服務(wù)端應(yīng)答一個 “Hello ****”。
http {
server {
listen 80;
location /test {
content_by_lua_block {
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
}
}
測試結(jié)果:
? ~ curl 127.0.0.1/test -d jack
hello nil
大家可以看到 data 部分獲取為空,如果你熟悉其他 web 開發(fā)框架,估計立刻就覺得 OpenResty 弱爆了。查閱一下官方 wiki 我們很快知道,原來我們還需要添加指令 lua_need_request_body 。究其原因,主要是 Nginx 誕生之初主要是為了解決負載均衡情況,而這種情況,是不需要讀取 body 就可以決定負載策略的,所以這個點對于 API Server 和 Web Application 開發(fā)的同學(xué)有點怪。
參看下面例子:
http {
server {
listen 80;
# 默認讀取 body
lua_need_request_body on;
location /test {
content_by_lua_block {
local data = ngx.req.get_body_data()
ngx.say("hello ", data)
}
}
}
}
再次測試,符合我們預(yù)期:
? ~ curl 127.0.0.1/test -d jack
hello jack
如果你只是某個接口需要讀取 body(并非全局行為),那么這時候也可以顯示調(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() 讀請求體,會偶爾出現(xiàn)讀取不到直接返回 nil 的情況。
如果請求體尚未被讀取,請先調(diào)用 ngx.req.read_body (或打開 lua_need_request_body 選項強制本模塊讀取請求體,此方法不推薦)。
如果請求體已經(jīng)被存入臨時文件,請使用 ngx.req.get_body_file 函數(shù)代替。
如需要強制在內(nèi)存中保存請求體,請設(shè)置 client_body_buffer_size 和 client_max_body_size 為同樣大小。
參考下面代碼:
http {
server {
listen 80;
# 強制請求 body 到臨時文件中(僅僅為了演示)
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)
}
}
}
}
測試結(jié)果:
? ~ curl 127.0.0.1/test -d jack
>> temp file: /Users/rain/Downloads/nginx/client_body_temp/0000000018
hello jack
由于 Nginx 是為了解決負載均衡場景誕生的,所以它默認是不讀取 body 的行為,會對 API Server 和 Web Application 場景造成一些影響。根據(jù)需要正確讀取、丟棄 body 對 OpenResty 開發(fā)是至關(guān)重要的。