ngx.req.socket
語法: tcpsock, err = ngx.req.socket()
語法: tcpsock, err = ngx.req.socket(raw)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
返回一個包含了下游連接的只讀的cosocket對象。在這個對象里面,只支持receive和receiveuntil方法。
在發(fā)生錯誤的情況下,將會返回一個nil值和一個描述錯誤的字符串。
這個方法返回的socket對象經(jīng)常被用來讀取請求的body,以一個流的方式。不要開啟lua_need_request_body指令,并且不要將這個調(diào)用與ngx.req.read_body和ngx.req.discard_body混合使用。
如果任何請求的body數(shù)據(jù)已經(jīng)被預(yù)讀到Nginx內(nèi)核請求header緩沖區(qū)中,結(jié)果cosocket對象要小心的處理這些來避免這種預(yù)讀取中潛在的數(shù)據(jù)丟失。分塊請求的body在這個API中不支持。
從v0.9.0版本開始,這個方法接受一個可選的 boolean raw參數(shù)。當(dāng)這個參數(shù)是true,這個方法返回一個全雙工的cosocket對象包裝原始的下游連接套接字,在這里你可以調(diào)用receive, receiveuntil, 和 send方法。
當(dāng)raw參數(shù)是true,要求這里沒有從之前ngx.say, ngx.print, 或者 ngx.send_headers 調(diào)用時未解決的數(shù)據(jù)存在。所以,如果你之前有這些下游輸出調(diào)用,你應(yīng)該在調(diào)用ngx.req.socket(true)之前調(diào)用ngx.flush(true)來保證這里沒有未解決的輸出數(shù)據(jù)。如果請求body還沒有被讀取,那么"raw socket"也可以被用來讀取請求的body。
你可以使用通過ngx.req.socket(true)返回的“raw request socket”來實現(xiàn)花哨的協(xié)議例如WebSocket,或者只是發(fā)出你自己的未加工的HTTP響應(yīng)頭或者body數(shù)據(jù)。你可以參考lua-resty-websocket library的一個真實世界的例子。
這個方法首先從v0.5.0rc1版本被介紹。
ngx.exec
語法: ngx.exec(uri,args?)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
做一個內(nèi)部重定向到uri附帶參數(shù)arg并且和echo-nginx-module中的echo_exec相似。
ngx.exec('/some-location');
ngx.exec('/some-location', 'a=3&b=5&c=6');
ngx.exec('/some-location?a=3&b=5', 'c=6');
這個可選的第二個參數(shù)args可以被用來指定額外的URI查詢參數(shù),例如:
ngx.exec("/foo", "a=3&b=hello%20world")
作為另一種選擇,一個Lua table中可以被當(dāng)做args參數(shù)傳遞,ngx_lua來展開URI轉(zhuǎn)義和字符串連接。
ngx.exec("/foo",{ a = 3, b = "hello world" })
這個結(jié)果和之前的例子是完全相同的。
通過Lua table傳遞args參數(shù)的形式和通過使用ngx.encode_args方法是完全一樣的。
同樣也支持命名的location但是第二個args參數(shù)將會被忽略掉,如果查詢字符串存在并且新location會繼承自以前的location(如果有的話)。
在下面的例子中,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
}
}
注意ngx.exec方法和ngx.redirect并不一樣,這是由于它是一個純粹的外部重定向并且不包括額外的HTTP流量。
并且注意這個方法調(diào)用終止當(dāng)前請求的處理并且它 必須 在ngx.send_headers或者ngx.print 或 ngx.say明確響應(yīng)body輸出之前調(diào)用。
建議編碼時候,將這個方法調(diào)用和return語句結(jié)合,例如:return ngx.exec(...)可以在除了header_filter_by_lua*之外的上下文中使用,以強調(diào)程序已經(jīng)被終止的事實。
ngx.redirect
語法: ngx.redirect(uri, status?)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
發(fā)出一個HTTP 301或者302重定向到uri。
這個可選的status參數(shù)指定要使用的HTTP狀態(tài)?,F(xiàn)在支持下面的狀態(tài)碼:
301-
302(默認(rèn)) 303307
默認(rèn)的是 302 (ngx.HTTP_MOVED_TEMPORARILY)
這里有一個例子,假設(shè)當(dāng)前的服務(wù)器名稱是localhost,并且監(jiān)聽的端口是 1984:
return ngx.redirect("/foo")
等價于
return ngx.redirect("/foo", ngx.HTTP_MOVED_TEMPORARILY)
支持重定向任意外部的URL,例如:
return ngx.redirect("http://www.google.com")
我們也可以直接使用數(shù)值代碼作為第二個status參數(shù):
return ngx.redirect("/foo",301)
這個方法和標(biāo)準(zhǔn)ngx_http_rewrite_module中的附帶redirect修飾符的rewrite 指令類似,例如,這個nginx.conf片段
rewrite ^ /foo? redirect; # nginx config
等價于下面的Lua代碼
return ngx.redirect('/foo'); -- Lua code
而
rewrite ^ foo? permanent; #nginx config
等價于
return ngx.redirect('/foo',ngx.HTTP_MOVED_PERMANENTLY) -- Lua code
也可以指定URI參數(shù),例如:
return ngx.redirect('/foo?a=3&b=4')
注意這個方法調(diào)用終止當(dāng)前請求的運行并且它 必須 在ngx.send_headers調(diào)用或者通過ngx.print或者 ngx.say明確響應(yīng)body輸出之前。
建議的編碼風(fēng)格是,將這個方法調(diào)用與一個return聲明結(jié)合,例如,return ngx.redirect(...)在除了header_filter_by_lua*之外的上下文中被接受,來強調(diào)一個事實就是這個請求處理已經(jīng)被終止了。
ngx.send_headers
語法: ok, err = ngx.send_headers()
上下文: rewrite_by_lua*,access_by_lua*,content_by_lua*
顯示的發(fā)送出響應(yīng)頭。
從v0.8.3版本這個方法在成功的時候返回1,在其他情況下返回一個nil和一個字符串描述錯誤。
注意通常情況下不需要手動發(fā)送出響應(yīng)頭,因為ngx_lua會在內(nèi)容通過 ngx.say 或者 ngx.print輸出之前自動的將響應(yīng)頭發(fā)出,或者當(dāng)content_by_lua*正常退出時。
ngx.headers_sent
語法: value = ngx.headers_sent
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
如果響應(yīng)頭被發(fā)出去了(通過ngx_lua)將會返回true,其他情況返回false。
這個API首先在ngx_lua v0.3.1rc6版本中被介紹。
ngx.print
語法: ok,err = ngx.print(...)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
發(fā)出已經(jīng)連接過的參數(shù)到HTTP客戶端(作為響應(yīng)body)。如果響應(yīng)頭沒有被發(fā)送,這個方法將會首先發(fā)出headers然后發(fā)出body數(shù)據(jù)。
從v0.8.3,這個方法在成功后返回1,在其他情況下返回nil和一個描述錯誤信息的字符串。
Lua nil值將會輸出"nil"字符串并且Lua boolean值將會分別輸出"true"和"false"文字字符串。
嵌套的字符串是數(shù)組是允許的并且數(shù)組中的元素將會被一個接著一個的輸出:
local table = {
"hello, ",
{"world: ", true, " or ", false,
{": ", nil}}
}
ngx.print(table)
將會產(chǎn)生輸出:
hello, world: true or false: nil
非數(shù)組的表參數(shù)將會導(dǎo)致拋出一個Lua異常。
這個ngx.null常量將會產(chǎn)生"null"字符串輸出。
這是一個異步的調(diào)用并且將會立即返回而不需要等待所有的數(shù)據(jù)要寫入系統(tǒng)發(fā)送緩存區(qū)中。要開啟同步模式,在調(diào)用ngx.print之后調(diào)用ngx.flush(true)。這個對流輸出特別有用。更多細(xì)節(jié)查看ngx.flush。
請注意一點ngx.print和 ngx.say會總是調(diào)用整個Nginx輸出body過濾鏈,這個是一個昂貴的操作。所以在一個緊密循環(huán)中無論調(diào)用哪一個都要小心。你自己在Lua中緩沖數(shù)據(jù)并且保存調(diào)用。
ngx.say
語法: ok, err = ngx.say(...)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
和ngx.print類似但是多發(fā)出一個換行符。
ngx.log
語法: ngx.log(log_level, ...)
上下文: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
通過給定的logging級別來連接參數(shù)到error.log中。
Lua nil參數(shù)是接受的,并且結(jié)果為文字的"nil"字符串,同時Lua boolean結(jié)果為文字的"true"或者"false"字符串輸出。并且ngx.null常量將會產(chǎn)生"null"字符串輸出。
這個log_level參數(shù)可以取常數(shù)例如ngx.ERR和ngx.WARN.檢查Nginx log level constants來獲取細(xì)節(jié)。
這里有個Nginx內(nèi)核硬編碼的2048字節(jié)的限制在錯誤信息長度上。這個限制包含結(jié)尾換行開頭的時間戳。如果信息大小超過了這個限制,Nginx會相應(yīng)的截取信息字符串。這個限制可以通過編輯在Nginx源碼樹種的src/core/ngx_log.h 文件的NGX_MAX_ERROR_STR宏定義來修改。
ngx.flush
語法: ok, err = ngx.flush(wait?)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
Flush 響應(yīng)輸出到客戶端。
ngx.flush接受一個可選的boolean wait參數(shù)(默認(rèn):false),首先在v0.3.1rc34版本中介紹。當(dāng)通過默認(rèn)的參數(shù)調(diào)用的時候,它纏身給一個異步的調(diào)用(立即返回而不等待輸出數(shù)據(jù)被寫入到系統(tǒng)的發(fā)送緩沖中)。通過wait參數(shù)設(shè)置為true調(diào)用這個方法會轉(zhuǎn)變?yōu)橥侥J健?/p>
在同步模式,這個方法將會不會返回直到所有的輸出數(shù)據(jù)已經(jīng)被寫入到系統(tǒng)輸出緩沖中或者直到send_timeout設(shè)置已經(jīng)過期了。注意使用Lua協(xié)同程序機(jī)制意味著這個方法并不阻塞Nginx事件循環(huán)及時在同步模式。
當(dāng)ngx.flush(true) 在ngx.print或者ngx.say之后被立即調(diào)用,這回導(dǎo)致后者的方法在同步模式下運行。這個在流輸出中特別有用。
注意ngx.flush在HTTP 1.0輸出緩沖模式中并不是一個功能。查看HTTP 1.0 support。
從v0.8.3開始這個方法在成功之后返回1,在其他情況下返回nil和一個字符串來描述錯誤。
ngx.exit
語法: ngx.exit(status)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
當(dāng)status >= 200 (例如,ngx.HTTP_OK和以上),它將會中斷當(dāng)前的請求并且返回狀態(tài)碼給nginx。
當(dāng)status == 0 (例如,ngx.OK),它將會退出當(dāng)前的階段處理器(或者內(nèi)容處理器如果 content_by_lua*指令被使用了)并且為當(dāng)前請求繼續(xù)運行后面的階段(如果有的話)。
這個status參數(shù)可以使ngx.OK, ngx.ERROR,ngx.HTTP_NOT_FOUND,ngx.HTTP_MOVED_TEMPORARILY,或者其他 HTTP status constants。
要返回一個包含當(dāng)前內(nèi)容的錯誤頁,可以使用像這樣的代碼片段:
ngx.status = ngx.HTTP_GONE
ngx.say("This is our own content")
-- to cause quit the whole request rather than the current phase handler
ngx.exit(ngx.HTTP_OK)
執(zhí)行的效果:
$ curl -i http://localhost/test
HTTP/1.1 410 Gone
Server: nginx/1.0.6
Date: Thu, 15 Sep 2011 00:51:48 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
This is our own content
數(shù)值文本可以直接被用在參數(shù)上,例如,
ngx.exit(501)
注意盡管這個方法接受所有的 HTTP status constants作為輸入,它只接受core constants中的NGX_OK和NGX_ERROR。
還要注意,這個方法調(diào)用歐冠終止當(dāng)前請求的處理并且建議的編碼風(fēng)格是將這個方法調(diào)用歐冠與一個return聲明連接,例如, return ngx.exit(...)被用來強調(diào)一個事實是請求處理已經(jīng)被終止了。
當(dāng)用在header_filter_by_lua*, balancer_by_lua*, 和
ssl_session_store_by_lua*的上下中時,ngx.exit()作為一個異步的操作將會立即返回。這個行為在未來可能會改變并且推薦用戶使用上面推薦的return來結(jié)合使用。
ngx.eof
語法: ok, err = ngx.eof()
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*
顯示的指定響應(yīng)輸出流的結(jié)束。在HTTP 1.1分塊編碼輸出的情況下,它將只是會觸發(fā)Nginx內(nèi)核發(fā)送出"last chunk"。
當(dāng)你在你下游連接中禁用了HTTP 1.1的keep-alive特性時,你可以調(diào)用這個方法來寫到HTTP client來主動的關(guān)閉連接。這個技巧可以用在做一些后臺工作而不讓HTTP客戶端等待連接,例如下面的例子:
location = /async {
keepalive_timeout 0;
content_by_lua_block {
ngx.say("got the task!")
ngx.eof() -- well written HTTP clients will close the connection at this point
-- access MySQL, PostgreSQL, Redis, Memcached, and etc here...
}
}
但是如果你創(chuàng)建子請求來訪問其他通過nginx upstream模塊配置的location,那么你應(yīng)該配置這些upstream模塊來忽略客戶端連接中斷,如果他們不是默認(rèn)情況的話。例如,在默認(rèn)情況下標(biāo)準(zhǔn)的ngx_http_proxy_module將會同時中斷子請求和主請求,當(dāng)客戶端重點連接時,所以在你的location塊ngx_http_proxy_module配置中開啟proxy_ignore_client_abort](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_client_abort) 指令是非常重要的。
proxy_ignore_client_abort on;
一個更好的來做后臺工作的方式是使用ngx.timer.atAPI接口。
從v0.8.3開始這個方法在成功時候返回1,在其他錯誤情況下返回nil和一個字符串描述。
ngx.sleep
語法: ngx.sleep(seconds)
上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
睡眠指定的描述而不阻塞。可以指定一個時間分辨率達(dá)到0.001秒(例如:一毫秒)。
在后面的場景,這個方法使用的是Nginx timers。
從0.7.20版本開始,這個0時間參數(shù)也可以被指定。
這個方法首先在0.5.0rc30版本中被介紹。
ngx.escape_uri
語法: newstr = ngx.escape_uri(str)
上下文: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
編碼str來作為URI組件。
ngx.unescape_uri
語法: newstr = ngx.unescape_uri(str)
上下文: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*
解碼str,str是一個編碼過的URI組件。
例如:
ngx.say(ngx.unescape_uri("b%20r56+7"))
得到輸出
b r56 7
ngx.encode_args
語法: str = ngx.encode_args(table)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*
根據(jù)URI的編碼規(guī)則編碼Lua table為一個查詢參數(shù)字符串。
例如,
ngx.encode_args({foo = 3, ["b r"] = "hello world"})
產(chǎn)生
foo=3&b%20r=hello%20world
這個table的keys必須是Lua字符串。
同時也支持多值查詢參數(shù)。使用一個lua table來作為參數(shù)值,例如:
ngx.encode_args({baz = {32, "hello"}})
得到
baz=32&baz=hello
如果這個value table為空那么影響等價于nil值。
同時也支持boolean參數(shù)值,例如,
ngx.encode_args({a = true, b = 1})
產(chǎn)生
a&b=1
如果這個參數(shù)值為false,那么影響等價于nil值。
這個方法首先在 v0.3.1rc27版本中被介紹。
ngx.decode_args
語法: table = ngx.decode_args(str, max_args?)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
將一個編碼過的查詢字符串解碼為一個Lua table。這個是ngx.encode_args的相反的方法。
這個可選的max_args參數(shù)可以被用來指定通過str參數(shù)解析的參數(shù)數(shù)量的最大值。默認(rèn)情況下,默認(rèn)解析100個請求參數(shù)(包括這些名字相同的)并且額外的URI參數(shù)會被默默的丟棄來防止?jié)撛诘木芙^服務(wù)攻擊。
這個參數(shù)可以被設(shè)置為0來移除對接受請求參數(shù)處理的限制:
local args = ngx.decode_args(str, 0)
強烈不建議移除max_args。
這個方法首先在v0.5.0rc29版本中被介紹。
encode_base64
語法: newstr = ngx.encode_base64(str, no_padding?)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
編碼str成為一個base64摘要。
從0.9.16版本開始,一個可選的boolean類型no_padding參數(shù)可以被指定來控制是否base64摘要應(yīng)該被追加到結(jié)果摘要中(默認(rèn)是false,例如,使用啟用追加)。
ngx.decode_base64
語法: newstr = ngx.decode_base64(str)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
解碼str參數(shù)將base64摘要成為一個原始的形式。如果str不是正常形式返回nil。
ngx.crc32_short
語法: intval = ngx.crc32_short(str)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
計算str字符串的CRC-32(循環(huán)冗余碼)摘要。
這個方法對較短的str輸入(例如,小于30~60bytes)表現(xiàn)較好,和ngx.crc32_long相比。這個結(jié)果和ngx.crc32_long完全一樣。
幕后的實現(xiàn),這個只是一個薄薄的對Nginx核心中的ngx_crc32_short的封裝。
這個API首先在v0.3.1rc8版本中被介紹。
ngx.crc32_long
語法: intval = ngx.crc32_long(str)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
計算參數(shù)str的HMAC-SHA1摘要,并且返回使用密鑰<secret_key>的結(jié)果。
原始字節(jié)形式的HMAC-SHA1證書將會生成,使用ngx.encode_base64,例如,如果需要的話將結(jié)果以結(jié)果的文本表示。
例如,
local key = "thisisverysecretstuff"
local src = "some string we want to sign"
local digest = ngx.hmac_sha1(key, src)
ngx.say(ngx.encode_base64(digest))
將會導(dǎo)致輸出:
R/pvxzHC4NLtj7S+kXFg/NePTmk=
這個API需要在Nginx編譯的時候開啟OpenSSL庫(通常在./configure腳本里面?zhèn)魅?code>--with-http_ssl_module參數(shù))
這個方法首先在v0.3.1rc29版本中被介紹。
ngx.md5
語法: ngx.md5(str)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
返回str參數(shù)的16進(jìn)制的MD5摘要。
例如,
location = /md5 {
content_by_lua_block { ngx.say(ngx.md5("hello")) }
}
產(chǎn)生輸出
5d41402abc4b2a76b9719d911017c592
查看ngx.md5_bin,如果需要原始的MD5摘要。
ngx.sha1_bin
語法: digest = ngx.sha1_bin(str)
上下文: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
返回str參數(shù)的二級制形式的SHA-1摘要。
這個方法需要在Nginx編譯時的SHA-1支持。(這個經(jīng)常意味著在構(gòu)建Nginx時需要安裝OpenSSL)
這個方法首先在v0.5.0rc6中被介紹。