【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解
源碼地址:https://github.com/Tinywan/Lua-Nginx-Redis
一、介紹
各種* _by_lua,* _by_lua_block和* _by_lua_file配置指令用作nginx.conf文件中Lua API的網(wǎng)關(guān)。 下面描述的Nginx Lua API只能在這些配置指令的上下文中運(yùn)行的用戶Lua代碼中調(diào)用。API以兩個(gè)標(biāo)準(zhǔn)軟件包ngx和ndk的形式暴露給Lua。 這些軟件包位于ngx_lua中的默認(rèn)全局范圍內(nèi),并且始終可在ngx_lua指令中使用。
這些包可以像這樣引入外部Lua模塊:
local say = ngx.saylocal _M = {}function _M.foo(a)say(a)endreturn _M強(qiáng)烈建議使用package.seeall標(biāo)志,因?yàn)槠涓鞣N不良的副作用。也可以直接要求外部Lua模塊中的包:
local ngx = require“ngx”local ndk = require“ndk”v0.2.1rc19版本中引入了需要這些軟件包的能力。
用戶代碼中的網(wǎng)絡(luò)I / O操作應(yīng)該只通過(guò)Nginx Lua API調(diào)用來(lái)完成,因?yàn)镹ginx事件循環(huán)可能被阻塞,否則性能會(huì)明顯下降。 磁盤(pán)操作與相對(duì)少量的數(shù)據(jù)可以使用標(biāo)準(zhǔn)的Lua io庫(kù),但巨大的文件讀寫(xiě)應(yīng)盡可能避免,因?yàn)樗麄兛赡軙?huì)顯著阻止Nginx進(jìn)程。 強(qiáng)烈建議將所有網(wǎng)絡(luò)和磁盤(pán)I / O操作委派給Nginx的子請(qǐng)求(通過(guò)ngx.location.capture方法等),以獲得最佳性能。
二、命令介紹
ngx.arg
語(yǔ)法:val = ngx.arg [index]
上下文:set_by_lua *,body_filter_by_lua *
描述:當(dāng)在set_by_lua *指令的上下文中使用時(shí),此表是只讀的,并保存config指令的輸入?yún)?shù):
value = ngx.arg[n]這里是一個(gè)例子
location /foo_sum {set $a 32;set $b 56;set_by_lua $sum'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])'$a $b;echo "sum = ${sum}";}CURL 運(yùn)行輸出
root@iZ236j3sofdZ:/usr/local/nginx/conf/lua# curl "http://localhost/foo_sum" sum = 88寫(xiě)出88,32和56的和。
當(dāng)在body_filter_by_lua *的上下文中使用此表時(shí),第一個(gè)元素將輸入數(shù)據(jù)塊保存到輸出過(guò)濾器代碼,第二個(gè)元素保存指示整個(gè)輸出數(shù)據(jù)流結(jié)束的“eof”標(biāo)志的布爾標(biāo)志。
傳遞給下游Nginx輸出過(guò)濾器的數(shù)據(jù)塊和“eof”標(biāo)志也可以通過(guò)將值直接分配給相應(yīng)的表元素來(lái)覆蓋。 當(dāng)將nil或空Lua字符串值設(shè)置為ngx.arg [1]時(shí),根本不會(huì)將數(shù)據(jù)塊傳遞到下游Nginx輸出過(guò)濾器。
ngx.null
ngx.null常量是一個(gè)NULL light用戶數(shù)據(jù),通常用于在Lua表等中表示nil值,類似于lua-cjson庫(kù)的cjson.null常量。 這個(gè)常數(shù)首先在v0.5.0rc5版本中引入。
ngx.var.VARIABLE?
語(yǔ)法:ngx.var.VAR_NAME
上下文:set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
讀取和寫(xiě)入Nginx變量值
value = ngx.var.some_nginx_variable_namengx.var.some_nginx_variable_name = value注意,只有已經(jīng)定義的nginx變量可以寫(xiě)入。 例如:
location /foo {set $my_var ''; # this line is required to create $my_var at config timecontent_by_lua_block {ngx.var.my_var = 123;...}}也就是說(shuō),nginx變量不能在運(yùn)行中創(chuàng)建。一些特殊的nginx變量,如args和args和?limit_rate可以分配一個(gè)值,許多其他變量不是,如querystring,querystring,arg_PARAMETER和httpNAME。通過(guò)寫(xiě)入ngx.var[1],ngx.var[2],ngx.var[3]等,也可以通過(guò)此接口讀取Nginx正則表達(dá)式組捕獲變量httpNAME。通過(guò)寫(xiě)入ngx.var[1],ngx.var[2],ngx.var[3]等,也可以通過(guò)此接口讀取Nginx正則表達(dá)式組捕獲變量?1,2,2,?3等。將ngx.var.Foo設(shè)置為nil值將取消設(shè)置$ Foo Nginx變量。
ngx.var.args = nil小心當(dāng)從Nginx變量讀取時(shí),Nginx將在每個(gè)請(qǐng)求的內(nèi)存池中分配內(nèi)存,只有在請(qǐng)求終止時(shí)才釋放內(nèi)存。 因此,當(dāng)您需要在Lua代碼中重復(fù)讀取Nginx變量時(shí),將Nginx變量值緩存到您自己的Lua變量中,例如:
local val = ngx.var.some_var--- use the val repeatedly later以防止(臨時(shí))內(nèi)存在當(dāng)前請(qǐng)求的生存期內(nèi)泄漏。 緩存結(jié)果的另一種方法是使用ngx.ctx表。未定義的NGINX變量評(píng)估為nil,而未初始化(但已定義)的NGINX變量將被評(píng)估為空的Lua字符串。此API需要相對(duì)昂貴的元方法調(diào)用,建議避免在熱代碼路徑上使用它。
Core constants
上下文:?init_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*
ngx.OK (0)ngx.ERROR (-1)ngx.AGAIN (-2)ngx.DONE (-4)ngx.DECLINED (-5)請(qǐng)注意,只有三個(gè)這些常數(shù)是由所利用的Nginx API為lua(即ngx.exit接受NGX_OK,NGX_ERROR和NGX_DECLINED作為輸入)。
ngx.null該ngx.null常數(shù)是一個(gè)NULL通常用來(lái)表示在Lua表等零值光用戶數(shù)據(jù)和類似于LUA-cjson庫(kù)的cjson.null常數(shù)。此常數(shù)最早在引入的v0.5.0rc5釋放。
待續(xù).........
HTTP方法常量
上下文:?init_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 *。
ngx.HTTP_GETngx.HTTP_HEADngx.HTTP_PUTngx.HTTP_POSTngx.HTTP_DELETEngx.HTTP_OPTIONS (added in the v0.5.0rc24 release)ngx.HTTP_MKCOL (added in the v0.8.2 release)ngx.HTTP_COPY (added in the v0.8.2 release)ngx.HTTP_MOVE (added in the v0.8.2 release)ngx.HTTP_PROPFIND (added in the v0.8.2 release)ngx.HTTP_PROPPATCH (added in the v0.8.2 release)ngx.HTTP_LOCK (added in the v0.8.2 release)ngx.HTTP_UNLOCK (added in the v0.8.2 release)ngx.HTTP_PATCH (added in the v0.8.2 release)ngx.HTTP_TRACE (added in the v0.8.2 release)這些常數(shù)通常在使用ngx.location.capture和ngx.location.capture_multi方法調(diào)用。
?
HTTP狀態(tài)常數(shù)
上下文:?init_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 *。
value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release)value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release)value = ngx.HTTP_OK (200)value = ngx.HTTP_CREATED (201)value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release)value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release)value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release)value = ngx.HTTP_SPECIAL_RESPONSE (300)value = ngx.HTTP_MOVED_PERMANENTLY (301)value = ngx.HTTP_MOVED_TEMPORARILY (302)value = ngx.HTTP_SEE_OTHER (303)value = ngx.HTTP_NOT_MODIFIED (304)value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release)value = ngx.HTTP_BAD_REQUEST (400)value = ngx.HTTP_UNAUTHORIZED (401)value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release)value = ngx.HTTP_FORBIDDEN (403)value = ngx.HTTP_NOT_FOUND (404)value = ngx.HTTP_NOT_ALLOWED (405)value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release)value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release)value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release)value = ngx.HTTP_GONE (410)value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release)value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release)value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release)value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release)value = ngx.HTTP_INTERNAL_SERVER_ERROR (500)value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release)value = ngx.HTTP_SERVICE_UNAVAILABLE (503)value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release)value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release)value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release)Nginx的日志級(jí)別常數(shù)
上下文:?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。
ngx.STDERRngx.EMERGngx.ALERTngx.CRITngx.ERRngx.WARNngx.NOTICEngx.INFOngx.DEBUG語(yǔ)法:?print(...)
上下文:?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*
寫(xiě)參數(shù)值到nginx的error.log與文件ngx.NOTICE日志級(jí)別。它相當(dāng)于
ngx.log(ngx.NOTICE, ...)Lua的nil參數(shù)被接受,并導(dǎo)致文字"nil"字符串,而Lua的布爾導(dǎo)致文字"true"或"false"字符串。和ngx.null常數(shù)將產(chǎn)生"null"串輸出。
有一個(gè)硬編碼2048在Nginx的核心錯(cuò)誤信息的長(zhǎng)度字節(jié)的限制。此限制包括尾隨換行符和領(lǐng)先的時(shí)間戳。如果郵件的大小超出此限制,Nginx的將相應(yīng)截?cái)嘞⑽谋尽?/span>這個(gè)限制可以通過(guò)編輯手動(dòng)修改NGX_MAX_ERROR_STR的宏定義src/core/ngx_log.h在Nginx的源代碼樹(shù)文件。
ngx.ctx
上下文:?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*
這個(gè)表可以被用來(lái)存儲(chǔ)每個(gè)請(qǐng)求的Lua上下文數(shù)據(jù),并具有使用壽命相同當(dāng)前請(qǐng)求(與Nginx的變量)。考慮下面的例子,
location /test {rewrite_by_lua_block {ngx.ctx.foo = 76}access_by_lua_block {ngx.ctx.foo = ngx.ctx.foo + 3}content_by_lua_block {ngx.say(ngx.ctx.foo)}}然后GET /test將產(chǎn)生的輸出:79
即,ngx.ctx.foo條目橫跨重寫(xiě),訪問(wèn)和請(qǐng)求的內(nèi)容相存在。每一項(xiàng)要求,其中包括子請(qǐng)求,有它自己的表的副本。例如:
location /sub {content_by_lua_block {ngx.say("sub pre: ", ngx.ctx.blah)ngx.ctx.blah = 32ngx.say("sub post: ", ngx.ctx.blah)}}location /main {content_by_lua_block {ngx.ctx.blah = 73ngx.say("main pre: ", ngx.ctx.blah)local res = ngx.location.capture("/sub")ngx.print(res.body)ngx.say("main post: ", ngx.ctx.blah)}}然后GET /main會(huì)給輸出:
main pre: 73sub pre: nilsub post: 32main post: 73在此,改性ngx.ctx.blah的子請(qǐng)求條目不會(huì)影響所述一個(gè)在父請(qǐng)求。這是因?yàn)樗麄冇袃蓚€(gè)獨(dú)立的版本ngx.ctx.blah。內(nèi)部重定向會(huì)破壞原來(lái)的請(qǐng)求ngx.ctx數(shù)據(jù)(如果有的話)和新要求將有一個(gè)空ngx.ctx表。例如:
location /new {content_by_lua_block {ngx.say(ngx.ctx.foo)}}location /orig {content_by_lua_block {ngx.ctx.foo = "hello"ngx.exec("/new")}}然后GET /orig會(huì)給:nil
而不是原來(lái)的"hello"值。任意的數(shù)據(jù)值,包括Lua的關(guān)閉和嵌套表,可以插入到這個(gè)“神奇”的表。它還允許自定義元方法的注冊(cè)。覆蓋ngx.ctx用一個(gè)新的Lua表也支持,例如:
ngx.ctx = { foo = 32, bar = 54 }當(dāng)在上下文中使用init_worker_by_lua *,此表只是有當(dāng)前的Lua處理程序的壽命相同。
在ngx.ctx查找需要相對(duì)昂貴元方法的調(diào)用,這是不是明確傳遞每個(gè)請(qǐng)求的數(shù)據(jù)沿著自己的函數(shù)參數(shù)慢得多。所以,不要濫用這個(gè)API保存你自己的函數(shù)的參數(shù),因?yàn)樗ǔ>哂蓄H有些性能的影響。因?yàn)槟г椒ǖ?#xff0c;從來(lái)沒(méi)有“本地”的ngx.ctx上由于Lua的模塊級(jí)的Lua的功能范圍之外的表工作者級(jí)的數(shù)據(jù)共享。例如,以下是壞:
-- mymodule.lualocal _M = {}-- the following line is bad since ngx.ctx is a per-request-- data while this <code>ctx</code> variable is on the Lua module level-- and thus is per-nginx-worker.local ctx = ngx.ctxfunction _M.main()ctx.foo = "bar"endreturn _M改用以下內(nèi)容:
-- mymodule.lualocal _M = {}function _M.main(ctx)ctx.foo = "bar"endreturn _M也就是說(shuō),讓調(diào)用者通過(guò)ctx表明確地通過(guò)一個(gè)函數(shù)的參數(shù)。
?
ngx.location.capture
語(yǔ)法:?res = ngx.location.capture(uri, options?)
上下文:?rewrite_by_lua *,* access_by_lua,content_by_lua *
是一個(gè)同步非阻塞的NGINX子請(qǐng)求uri
NGINX的子請(qǐng)求提供了一個(gè)非常強(qiáng)大的方式去實(shí)現(xiàn)非阻塞的內(nèi)部請(qǐng)求,或者其他的C模塊,比如?ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, 甚至ngx_lua自己等等。
當(dāng)然,這些子請(qǐng)求僅僅是模擬HTTP請(qǐng)求,但是并沒(méi)有額外的?HTTP/TCP,所有的進(jìn)程都是C級(jí)別的
子請(qǐng)求完全不同與HTTP 301/302。
這里有個(gè)基本的例子:
res = ngx.location.capture(uri)返回與4插槽,一個(gè)Lua表:res.status,res.header,res.body,和res.truncated。
res.status?用于保存子請(qǐng)求響應(yīng)的響應(yīng)狀態(tài)代碼。
res.header持有子請(qǐng)求的響應(yīng)頭,這是一個(gè)正常的Lua表。對(duì)于多值響應(yīng)頭,該值是保存所有的順序它們出現(xiàn)的值的Lua(陣列)表。例如,如果子請(qǐng)求響應(yīng)報(bào)頭包含以下幾行:
返回一個(gè)LUA的TABLE,三個(gè)值(res.status, res.header, and res.body)。
res.header包含了所有的子請(qǐng)求的頭的信息,它是一個(gè)普通的LUA TABLE。比如多個(gè)值的相應(yīng)頭,他們以數(shù)組的形式按照順序返回出現(xiàn)。例如:子請(qǐng)求包含了如下信息:
Set-Cookie: a=3Set-Cookie: foo=barSet-Cookie: baz=blah然后res.header["Set-Cookie"]將被評(píng)估,以表中的值?{"a=3", "foo=bar", "baz=blah"}。
res.body持有子請(qǐng)求的響應(yīng)體數(shù)據(jù),這些數(shù)據(jù)可能會(huì)被截?cái)唷D憧偸切枰獧z查res.truncated布爾標(biāo)志,看是否res.body包含截?cái)鄶?shù)據(jù)。這里的數(shù)據(jù)截?cái)嘀荒苡赡切┎豢苫謴?fù)的錯(cuò)誤在你的子請(qǐng)求一樣,遠(yuǎn)端中止在響應(yīng)體數(shù)據(jù)流的中間,或當(dāng)你的子請(qǐng)求接收從響應(yīng)體數(shù)據(jù)的讀取超時(shí)發(fā)生過(guò)早的連接的情況下造成的遙控器。URI查詢串可以串聯(lián)到的URI本身,例如:
res = ngx.location.capture('/foo/bar?a=3&b=4')像名為位置@foo不允許由于nginx的核心的限制。使用與組合正常位置internal指令準(zhǔn)備僅供內(nèi)部使用的位置。
可選選項(xiàng)表可以喂的第二個(gè)參數(shù),它支持的選項(xiàng):
- method?指定子請(qǐng)求的請(qǐng)求方法,只接受常量一樣ngx.HTTP_POST。
- body?指定子請(qǐng)求的請(qǐng)求體(僅字符串值)。
- args?指定子請(qǐng)求的URI查詢參數(shù)(這兩個(gè)字符串值和Lua表被接受)
- ctx?指定一個(gè)Lua表是ngx.ctx為子請(qǐng)求表。它可以是當(dāng)前請(qǐng)求的ngx.ctx表,這有效地使母體和其子請(qǐng)求共享完全相同的上下文表。此選項(xiàng)最初是在引進(jìn)v0.3.1rc25發(fā)行。
- vars?采取持有的值設(shè)置指定的Nginx變量在子請(qǐng)求作為此選項(xiàng)的值一個(gè)Lua表。此選項(xiàng)最初是在引進(jìn)v0.3.1rc31發(fā)行。
- copy_all_vars?指定是否在當(dāng)前請(qǐng)求所討論的子請(qǐng)求的所有的Nginx變量值復(fù)制。在子請(qǐng)求nginx的變量的修改將不會(huì)影響當(dāng)前(父)的請(qǐng)求。此選項(xiàng)最初是在引進(jìn)v0.3.1rc31發(fā)行。
- share_all_vars?指定是否共享的子請(qǐng)求與當(dāng)前(父)要求所有的Nginx變量。在子請(qǐng)求Nginx的變量的修改將影響當(dāng)前(父)的請(qǐng)求。啟用此選項(xiàng)可能會(huì)導(dǎo)致因不良副作用難以調(diào)試問(wèn)題,被認(rèn)為是不好的,有害的。只有啟用該選項(xiàng),當(dāng)你完全知道自己在做什么。
- always_forward_body?當(dāng)設(shè)置為true,當(dāng)前(父)的請(qǐng)求的請(qǐng)求體總是會(huì)被轉(zhuǎn)發(fā)到,如果創(chuàng)建的子請(qǐng)求body未指定選項(xiàng)。無(wú)論是通過(guò)讀取請(qǐng)求體()ngx.req.read_body或lua_need_request_body上會(huì)被直接轉(zhuǎn)發(fā)到子請(qǐng)求不創(chuàng)建子請(qǐng)求(無(wú)論請(qǐng)求體數(shù)據(jù)在內(nèi)存中緩存或臨時(shí)文件緩存)時(shí)復(fù)制整個(gè)請(qǐng)求體數(shù)據(jù)。默認(rèn)情況下,這個(gè)選項(xiàng)是false和時(shí)body沒(méi)有指定選項(xiàng)時(shí),當(dāng)前的(父)請(qǐng)求的請(qǐng)求體,當(dāng)子請(qǐng)求取只轉(zhuǎn)發(fā)PUT或POST請(qǐng)求方法。
發(fā)出一個(gè)POST子請(qǐng)求,例如,可以做如下:
res = ngx.location.capture('/foo/bar',{ method = ngx.HTTP_POST, body = 'hello, world' })看到比其他POST HTTP方法的常量方法。該method選項(xiàng)是ngx.HTTP_GET默認(rèn)。
該args選項(xiàng)可以指定額外的URI參數(shù),例如:
ngx.location.capture('/foo?a=1',{ args = { b = 3, c = ':' } })相當(dāng)于
ngx.location.capture('/foo?a=1&b=3&c=%3a')也就是說(shuō),該方法將根據(jù)規(guī)則URI參數(shù)逃脫鍵和值一起將它們連接起來(lái)成為一個(gè)完整的查詢字符串。對(duì)于作為通過(guò)的Lua表的格式args參數(shù)是相同于使用的格式ngx.encode_args方法。該args選項(xiàng)也可以采取簡(jiǎn)單的查詢字符串:
ngx.location.capture('/foo?a=1',{ args = 'b=3&c=%3a' } })這在功能上等同于前面的例子。
該share_all_vars選項(xiàng)控制是否將當(dāng)前請(qǐng)求和子請(qǐng)求之間共享nginx的變量。如果此選項(xiàng)設(shè)置為true,那么當(dāng)前請(qǐng)求和相關(guān)的子請(qǐng)求將共享相同的Nginx變量的作用域。因此,通過(guò)一個(gè)子請(qǐng)求更改了Nginx的變量將影響到當(dāng)前的請(qǐng)求。
應(yīng)小心使用此選項(xiàng),變量的作用域共享可以有意想不到的副作用。的args,vars或copy_all_vars選項(xiàng)通常優(yōu)于代替。這個(gè)選項(xiàng)被設(shè)置為false默認(rèn)
location /other {set $dog "$dog world";echo "$uri dog: $dog";}location /lua {set $dog 'hello';content_by_lua_block {res = ngx.location.capture("/other",{ share_all_vars = true });ngx.print(res.body)ngx.say(ngx.var.uri, ": ", ngx.var.dog)}}訪問(wèn)位置/lua給:
/other dog: hello world /lua: hello world該copy_all_vars選項(xiàng)提供父請(qǐng)求的Nginx的變量的副本子請(qǐng)求時(shí)這樣子請(qǐng)求發(fā)出。由這樣子請(qǐng)求對(duì)這些變量所做的更改不會(huì)影響父請(qǐng)求或任何其他子請(qǐng)求共享父請(qǐng)求的變量。
location /other {set $dog "$dog world";echo "$uri dog: $dog";}location /lua {set $dog 'hello';content_by_lua_block {res = ngx.location.capture("/other",{ copy_all_vars = true });ngx.print(res.body)ngx.say(ngx.var.uri, ": ", ngx.var.dog)}}請(qǐng)求GET /lua將給輸出
/other dog: hello world /lua: hello請(qǐng)注意,如果兩者share_all_vars并copy_all_vars都設(shè)置為true,則share_all_vars優(yōu)先。
除了上述兩個(gè)設(shè)置,有可能使用在子請(qǐng)求變量的值vars選項(xiàng)。這些變量的變量共享或復(fù)制已評(píng)估后設(shè)置,并且提供了對(duì)編碼它們以URL參數(shù),并在Nginx的配置文件反向轉(zhuǎn)義它們傳遞特定值應(yīng)用于一個(gè)子請(qǐng)求的更有效的方法:
location /other {content_by_lua_block {ngx.say("dog = ", ngx.var.dog)ngx.say("cat = ", ngx.var.cat)}}location /lua {set $dog '';set $cat '';content_by_lua_block {res = ngx.location.capture("/other",{ vars = { dog = "hello", cat = 32 }});ngx.print(res.body)}}訪問(wèn)/lua將產(chǎn)生的輸出:
dog = hello cat = 32該ctx選項(xiàng)可用于指定自定義的Lua表作為ngx.ctx為子請(qǐng)求表。
location /sub {content_by_lua_block {ngx.ctx.foo = "bar";}}location /lua {content_by_lua_block {local ctx = {}res = ngx.location.capture("/sub", { ctx = ctx })ngx.say(ctx.foo);ngx.say(ngx.ctx.foo);}}然后請(qǐng)求GET /lua 輸出:
bar nil另外,也可以使用這個(gè)ctx選項(xiàng)共享同一ngx.ctx電流(父)請(qǐng)求和子請(qǐng)求之間的表:
location /sub {content_by_lua_block {ngx.ctx.foo = "bar";}}location /lua {content_by_lua_block {res = ngx.location.capture("/sub", { ctx = ngx.ctx })ngx.say(ngx.ctx.foo);}}請(qǐng)求GET /lua產(chǎn)生的輸出:bar
注意,通過(guò)發(fā)出子請(qǐng)求ngx.location.capture默認(rèn)繼承當(dāng)前請(qǐng)求的所有請(qǐng)求頭,而這可能對(duì)子請(qǐng)求響應(yīng)意想不到的副作用。例如,使用標(biāo)準(zhǔn)時(shí),ngx_proxy模塊服務(wù)子請(qǐng)求,“接受編碼:gzip”中的主要請(qǐng)求頭,可能會(huì)導(dǎo)致不能在Lua代碼正確處理gzip壓縮的響應(yīng)。原始請(qǐng)求頭,應(yīng)通過(guò)設(shè)置被忽略?proxy_pass_request_headers到off的子請(qǐng)求的位置。
如果body沒(méi)有指定選項(xiàng),且always_forward_body選項(xiàng)為false(默認(rèn)值),POST以及PUT子請(qǐng)求將繼承父請(qǐng)求(如果有的話)的請(qǐng)求主體。
上有可能為每一個(gè)主要請(qǐng)求并發(fā)子請(qǐng)求的數(shù)目的硬編碼上限。在舊版本Nginx的,下限為50并行子請(qǐng)求,并在最近的版本中,Nginx的1.1.x開(kāi)始,這是提高到200并發(fā)子請(qǐng)求。當(dāng)超過(guò)此限制時(shí),以下錯(cuò)誤消息被添加到error.log文件中:
[error] 13983#0: *1 subrequests cycle while processing "/uri"極限可以根據(jù)需要通過(guò)編輯的定義手動(dòng)修改NGX_HTTP_MAX_SUBREQUESTS宏中nginx/src/http/ngx_http_request.h在Nginx的源樹(shù)文件。請(qǐng)同時(shí)參閱限制捕獲由配置位置的其他模塊的子請(qǐng)求指示。
?
ngx.location.capture_multi
ngx.status
ngx.header.HEADER
ngx.resp.get_headers
?
ngx.req.is_internal
?
ngx.req.start_time
語(yǔ)法:?secs = ngx.req.start_time()
上下文:?set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
返回表示時(shí)間戳(包括毫秒作為小數(shù)部分)已創(chuàng)建當(dāng)前請(qǐng)求時(shí)一個(gè)浮點(diǎn)數(shù)。下面的例子模擬了$request_time變量值(由提供ngx_http_log_module純LUA):
| 1 | local request_time = ngx.now() - ngx.req.start_time() |
ngx.req.http_version
語(yǔ)法:??num = ngx.req.http_version()
背景:?set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *
返回當(dāng)前請(qǐng)求作為L(zhǎng)ua的數(shù)字的HTTP版本號(hào)。
當(dāng)前可能的值是2.0,1.0,1.1和0.9。返回nil了無(wú)法識(shí)別的值。
ngx.req.raw_header
語(yǔ)法:??str = ngx.req.raw_header(no_request_line?)
背景:?set_by_lua *,* rewrite_by_lua,access_by_lua *,* content_by_lua,header_filter_by_lua *
返回由Nginx的服務(wù)器接收到的原始原始的HTTP協(xié)議頭。
默認(rèn)情況下,請(qǐng)求行和尾隨CR LF終止也將包括在內(nèi)。例如,
ngx.print(ngx.req.raw_header())給出這樣的事情:
GET /t HTTP/1.1 Host: localhost Connection: close Foo: bar你可以指定可選的?no_request_line參數(shù)作為true排除從結(jié)果的請(qǐng)求行的值。例如
ngx.print(ngx.req.raw_header(true))輸出是這樣的:
Host: localhost Connection: close Foo: bar此方法不會(huì)在HTTP / 2請(qǐng)求工作尚未
?
CDN 反向代理LiveNode節(jié)點(diǎn),通過(guò)Lua腳本操作Redis數(shù)據(jù)庫(kù)實(shí)現(xiàn)轉(zhuǎn)發(fā)
URL訪問(wèn)地址:http://127.0.0.1/hls/4953.m3u8
nginx.conf 配置
location ~ \/.+\/.+\.(m3u8|ts) {#設(shè)置nginx變量if ($uri ~ \/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)(|-).*\.(m3u8|ts)) {set $app_name $1;set $a $2;}set $stream_id "";default_type 'text/html';lua_code_cache on;rewrite_by_lua_file /home/www/lua-tinywan/set_by_file.lua;#echo "stream_id :" $stream_id;proxy_buffering off;proxy_redirect off;proxy_connect_timeout 10;proxy_send_timeout 30;proxy_read_timeout 30;proxy_pass $stream_id;}set_by_file.lua 添加一下內(nèi)容:-- 接受Nginx傳遞進(jìn)來(lái)的參數(shù)$1 也就是SteamName local stream_a = ngx.var.alocal redis = require("resty.redis"); -- 創(chuàng)建一個(gè)redis對(duì)象實(shí)例。在失敗,返回nil和描述錯(cuò)誤的字符串的情況下 local redis_instance = redis:new(); --設(shè)置后續(xù)操作的超時(shí)(以毫秒為單位)保護(hù),包括connect方法 redis_instance:set_timeout(1000) --建立連接 local ip = '127.0.0.1' local port = 6379 --嘗試連接到redis服務(wù)器正在偵聽(tīng)的遠(yuǎn)程主機(jī)和端口 local ok,err = redis_instance:connect(ip,port) if not ok thenngx.say("connect redis error : ",err)return err end-- 權(quán)限驗(yàn)證 local res,err = redis_instance:auth('tinywanredis') if not res thenngx.say("failed to authenticate: ", err)return end--數(shù)據(jù)庫(kù)選擇 redis_instance:select(2)--調(diào)用API獲取數(shù)據(jù) local resp, err = redis_instance:hget("StreamLiveNodeInnerIp:"..stream_a,'livenode') if not resp thenngx.say("get msg error : ", err)return err end--得到的數(shù)據(jù)為空處理 if resp == ngx.null thenngx.say("this is not redis_data")return nil end ngx.var.stream_id = resp -- ngx.say("reds get result : ", resp)
?思路圖片:
?
?
貴在堅(jiān)持,相信自己.總結(jié)
以上是生活随笔為你收集整理的【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 阿里云全球首次互联网8K直播背后的技术解
- 下一篇: lua.c:80:31: fatal e