lua-resty-http上傳資料
lua-resty-http是一個基于Openresty/ngx_lua的HTTP用戶端,支援POST方法上傳資料。用法很簡單。
content_by_lua_block {
local http = require "resty.http"
local httpc = http:new()
local res = httpc:request_uri("http://www.baidu.com/", {
method = "POST",
body= "Hello, Lua!",
headers = {
["User-Agent"] = "lua-resty-http",
}
})
if not res then
return
end
ngx.log(ngx.ERR, "status: ", res.status)
}
request_uri這個方法用于向http://www.baidu.com/發送POST請求,包體内容為"Hello, Lua!"。
HTTP中傳輸包體
HTTP協定中,有包體需要發送時,需要有方法辨別包體的結束,這樣對方才能判斷是否接收到了完整的包體。判斷方法有兩個。
包體的長度确定時,HTTP請求頭部有Content-Length字段,标記包體的長度
包體長度不确定時,使用分塊傳輸。請求頭部有"Transfer-Encoding:chunked"表示傳輸包體是chunked編碼的
對于lua-resty-http, 通過request_uri發送請求時包體的内容由參數中的body指定。body可以是一個lua字元串或者lua中的table。
body為字元串時,包體長度為字元串長度,lua-resty-http會為請求添加Content-Length字段,标記包體的長度
body為table時,lua-resty-http不會添加Content-Length頭部,也不會為進行chunked編碼,而是直接将table中所有成員組合成字元串發送出去
若要通過lua-resty-http以chunked編碼上傳資料,必須自己為資料進行chunked編碼。
chunked編碼
如果一個HTTP消息(請求消息或應答消息)的Transfer-Encoding消息頭的值為chunked,那麼,消息體由數量未定的塊組成,并以最後一個大小為0的塊為結束。
每一個非空的塊都以該塊包含資料的位元組數(位元組數以十六進制表示)開始,跟随一個CRLF (回車及換行),然後是資料本身,最後塊CRLF結束。在一些實作中,塊大小和CRLF之間填充有白空格(0x20)。
最後一塊是單行,由塊大小(0),一些可選的填充白空格,以及CRLF。最後一塊不再包含任何資料,但是可以發送可選的尾部,包括消息頭字段。
消息最後以CRLF結尾。
例如包體為"Hello, Lua!",長度為10, 轉換成16進制為a,則編碼後的結果為"a\r\nHello,Lua!\r\n0\r\n\r\n",最後面跟的"0\r\n\r\n"沒有包含任何資料,隻是表示包體結束。
lua-resty-http 上傳chunked編碼資料
利用lua-resty-http以chunked編碼上傳資料,需要手動進行chunked編碼,同時設定Transfer-Encoding頭部。
下面是一個示例,為了簡單直接通過string.rep生成一個長字元串作為包體,string.format("%x", #raw_data)将字元串長度轉換為十六進制格式。
content_by_lua_block {
local http = require "resty.http"
local httpc = http:new()
local raw_data = string.rep("asdfgh", 512)
local chunked = {
string.format("%x", #raw_data),
"\r\n",
raw_data,
"\r\n",
"0\r\n\r\n",
}
local res = httpc:request_uri("http://www.baidu.com/", {
method = "POST",
body= chunked,
headers = {
["User-Agent"] = "lua-resty-http",
["Transfer-Encoding"] = "chunked",
}
})
if not res then
return
end
ngx.log(ngx.ERR, "status: ", res.status)
}