ngx_lua模块的原理:
- 每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM;
- 将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问;
- 每个外部请求都由一个Lua协程处理,协程之间数据隔离;
- Lua代码调用I/O操作等异步接口时,会挂起当前协程(并保护上下文数据),而不阻塞worker;
- I/O等异步操作完成时还原相关协程上下文数据,并继续运行
系列文章:
指令:openResty中ngx_lua模块提供的指令
常量:openResty中ngx_lua模块提供的常量
API:openResty中ngx_lua模块提供的API
三、API
3.1 print
语法: 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*
等同于:
ngx.log(ngx.NOTICE, ...)
3.2 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*
仅在同一个请求内全局,或者可以理解为同一个location内
location /sub { content_by_lua_block { ngx.say("sub pre: ", ngx.ctx.blah) ngx.ctx.blah = 32 ngx.say("sub post: ", ngx.ctx.blah) } } location /main { content_by_lua_block { ngx.ctx.blah = 73 ngx.say("main pre: ", ngx.ctx.blah) local res = ngx.location.capture("/sub") //发起新的子请求 ngx.print(res.body) ngx.say("main post: ", ngx.ctx.blah) } }
main pre: 73 sub pre: nil sub post: 32 main post: 73
3.3 ngx.location.capture、ngx.location.capture_multi
语法: res = ngx.location.capture(uri, options?)
语法: res1, res2, … = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, … })
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
例如:
local res = ngx.location.capture(uri, options)
res.status: res.header:返回头部信息,如 res.header["Set-Cookie"],返回{"a=3","foo=bar","baz=blah"} res.body: res.truncated:
options:
method: body: args: ctx: vars: copy_all_vars: share_all_vars: always_forward_body:
参考:openResty中的ngx.location.capture和ngx.location.capture_multi的使用
3.4 ngx.status
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
设置 nginx的输出status.
3.5 ngx.header.HEADER、ngx.resp.get_headers
语法: ngx.header.HEADER = VALUE
语法: value = ngx.header.HEADER
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
设置 nginx的输出header.
示例:
ngx.header.content_type = 'text/plain'; --等于 ngx.header["Content-Type"] = 'text/plain' ngx.header["X-My-Header"] = 'blah blah'; --等于 ngx.header.x_my_header = 'blah blah'
删除示例:
ngx.header["X-My-Header"] = nil; ngx.header["X-My-Header"] = {};
语法: headers = ngx.resp.get_headers(max_headers?, raw?)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, balancer_by_lua*
获取所有的响应头。
local headers = ngx.resp.get_headers() for k, v in pairs(headers) do ngx.say(k,":", v) end
3.6 ngx.req.raw_header、ngx.req.get_headers
语法: str = ngx.req.raw_header(no_request_line?)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
获取请求头部信息,返回字符串。
local header = ngx.req.raw_header() local header_no_request_line = ngx.req.raw_header(true) ngx.say(header) ngx.say(header_no_request_line)
输出:
GET /app/detail HTTP/1.1 Host: xopen.100.com:8080 User-Agent: curl/7.43.0 Accept: */* Host: xopen.100.com:8080 User-Agent: curl/7.43.0 Accept: */*
语法: headers = ngx.req.get_headers(max_headers?, raw?)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
获取请求头部信息,返回table。
参数:max_headers,限制获取数量,默认100,0为不限制。
参数:raw,是否大小写,默认为false。详细看下面的栗子。
local h = ngx.req.get_headers(10) for k, v in pairs(h) do ngx.say(k..":"..v) end ngx.say(h["User-Agent"]) --curl/7.43.0 ngx.say(h["user-agent"]) --curl/7.43.0 ngx.say(h.user_agent) --curl/7.43.0 ngx.say(h.User_Agent) --curl/7.43.0 local h = ngx.req.get_headers(10,true) for k, v in pairs(h) do ngx.say(k..":"..v) end ngx.say(h["User-Agent"]) --curl/7.43.0 ngx.say(h["user-agent"]) -- nil ngx.say(h.user_agent) -- nil ngx.say(h.User_Agent) -- nil
输出:
host:xopen.100.com:8080 accept:*/* user-agent:curl/7.43.0 curl/7.43.0 curl/7.43.0 curl/7.43.0 curl/7.43.0 Host:xopen.100.com:8080 User-Agent:curl/7.43.0 Accept:*/* curl/7.43.0 nil nil nil
3.7 ngx.req.is_internal
语法: is_internal = ngx.req.is_internal()
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
判断是否nginx内部跳转,等于 false表示为外部请求。
3.8 ngx.req.start_time
语法: 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*
计算请求的执行时间,可以模拟nginx中的 $request_time
ngx.update_time() local request_time = ngx.now() - ngx.req.start_time()
tips 01:在openResty中的时间都是缓存时间(同一个请求内),必须使用 ngx.update_time() 更新后,才能获取到当前的准确时间。
tips 02:使用该方法也可以比较下 lua_code_cache 开启和关闭时,请求执行的时间。比较后发现相差很多噢….
tips 03:有一个困惑,如下代码:
local a = 0 for i = 1, 100, 1 do a = a + 1 end ngx.update_time() local request_time = ngx.now() - ngx.req.start_time() ngx.say(ngx.now()) ngx.say(ngx.req.start_time()) ngx.say(request_time)
输出:
1511859137.633 1511859137.631 0.0019998550415039 --相减后成这样的勒!!
3.9 ngx.today、ngx.time、ngx.now、ngx.update_time、ngx.localtime、ngx.utctime、ngx.cookie_time、ngx.http_time、ngx.parse_http_time
作用域: 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 = ngx.today()
local today = ngx.today() ngx.say(today) -- 2017-11-28
语法: secs = ngx.time()
local secs = ngx.time() ngx.say(secs) -- 1511859418
语法: secs = ngx.now()
local secs = ngx.now() ngx.say(secs) -- 1511859590.807
语法: ngx.update_time()
tips 04:更新当前请求内的缓存时间,但ngx.req.start_time不会被更新。
语法: str = ngx.localtime()
local date = ngx.localtime() ngx.say(date) -- 2017-11-28 09:02:13
语法: str = ngx.utctime()
local date = ngx.utctime() ngx.say(date) -- 2017-11-28 09:02:13
语法: str = ngx.cookie_time(sec)
返回cookie过期时间的字符串。
local date = ngx.cookie_time(ngx.time()) ngx.say(date) -- Tue, 28-Nov-17 09:20:13 GMT
语法: str = ngx.http_time(sec)
返回http头部的Date的字符串。我们可以看到响应的头部都会有一个Date,就是这个东东生成的字符串。
local date = ngx.http_time(ngx.time()) ngx.say(date) -- Tue, 28 Nov 2017 09:22:24 GMT
语法: sec = ngx.parse_http_time(str)
格式化字符串,返回时间戳或nil.
local date = ngx.parse_http_time("Tue, 28 Nov 2017 09:24:32 GMT") ngx.say(date)
3.10 ngx.req.http_version
语法: num = ngx.req.http_version()
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
返回请求协议的版本。
local http_protocol = ngx.req.http_version() ngx.say(http_protocol) -- 1.1
3.11 ngx.req.get_method、ngx.req.set_method
语法: method_name = ngx.req.get_method()
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua*
获取当前请求的方法。例如 GET、POST
语法: ngx.req.set_method(method_id)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
设置子请求的方法。注意参数是method的id,即必须使用ngx.HTTP_GET、ngx.HTTP_POST设置,具体可参考:openResty中ngx_lua模块提供的常量
3.12 ngx.req.set_uri、ngx.req.set_uri_args
tips 05:这是一组非常实用的API,完全可以替换nginx中rewrite模块。主要应用在 rewrite_by_lua*模块内。
语法: ngx.req.set_uri(uri, jump?)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
语法: ngx.req.set_uri_args(args)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
ngx.req.set_uri("/foo", true) 相当于 rewrite ^ /foo last;
ngx.req.set_uri("/foo", false) 相当于 rewrite ^ /foo break; 相当于 ngx.req.set_uri("/foo")
示例:
location /test { rewrite_by_lua_block { local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "/$1", "o") ngx.req.set_uri(uri) } proxy_pass http://my_backend; }
rewrite ^ /foo?a=3? last; 相当于 ngx.req.set_uri_args("a=3") ngx.req.set_uri("/foo", true) 相当于 ngx.req.set_uri_args({a = 3}) ngx.req.set_uri("/foo", true)
示例:
location /test { set_by_lua_block $res { ngx.req.set_uri_args({a=1,aa=11}) ngx.req.set_uri(ngx.var.uri.."/set_lua_by_block") } rewrite_by_lua_block { ngx.req.set_uri_args({b=2,bb=22}) ngx.req.set_uri(ngx.var.uri.."/rewrite_lua_by_block") } access_by_lua_block { ngx.req.set_uri_args({c=3,cc=33}) ngx.req.set_uri(ngx.var.uri.."/access_by_lua_block") } content_by_lua_block { local args = ngx.req.get_uri_args() for k, v in pairs(args) do ngx.say(k,":",v) end ngx.say(ngx.var.uri) } }
输出:
cc:33
c:3
/test/set_lua_by_block/rewrite_lua_by_block/access_by_lua_block
下面是一个nginx的rewrite的代码
rewrite ^/$ /index.php break; rewrite ^/index\.html$ /index.php break; rewrite ^/case\.html$ /vcase.php break; rewrite ^/case/([0-9a-zA-Z]+)\.html$ /vcase.php?iid=$1 break; rewrite ^/mobile\.html$ /vmobile.php break; rewrite ^/email\.html$ /vemail.php break; rewrite ^/mail\.html$ /vmail.php break; rewrite ^/mail/([0-9a-zA-Z]+)\.html$ /vmail.php?iid=$1 break; rewrite ^/hosting\.html$ /vhosting.php break; rewrite ^/flow\.html$ /vflow.php break; rewrite ^/news\.html$ /vnews.php break; rewrite ^/news/([0-9a-zA-Z]+)/?$ /vnews.php?do=$1 break; rewrite ^/news/([0-9a-zA-Z]+)/([0-9a-zA-Z]+)\.html$ /vnews.php?do=$1&iid=$2 break;
使用ngx_lua替换:
local rules = { ["^/$"] = "/php/index.php", ["^/index.html$"] = "/php/index.php", ["^/case.html$"] = "/php/vcase.php", ["^/case/([0-9a-zA-Z]+).html$"] = "/php/vcase.php?iid=$1", ["^/mobile.html$"] = "/php/vmobile.php", ["^/email.html$"] = "/php/vemail.php", ["^/mail.html$"] = "/php/vmail.php", ["^/mail/([0-9a-zA-Z]+).html$"] = "/php/vmail.php?iid=$1", ["^/hosting.html$"] = "/php/vhosting.php", ["^/flow.html$"] = "/php/vflow.php", ["^/news.html$"] = "/php/vnews.php", ["^/news/([0-9a-zA-Z]+).html$"] = "/php/vnews.php?do=$1", ["^/news/([0-9a-zA-Z]+)/([0-9a-zA-Z]+).html$"] = "/php/vnews.php?do=$1&iid=$2", } local replaceUri = "" for pattern, replace in pairs(rules) do local uri, n, _ = ngx.re.sub(ngx.var.uri, pattern, replace, "jo") if n > 0 then replaceUri = uri break end end if replaceUri ~= "" then local splits = string:split(replaceUri, "?") if splits[2] then ngx.req.set_uri_args(splits[2]) end ngx.req.set_uri(splits[1],true) end
ngx的正则表达式参考:openResty中正则表达式的使用
注:虽然看上去使用 ngx_lua更复杂了,但碰到复杂的 rewrite 的时,就派上大用场了。
3.13 ngx.req.get_uri_args、ngx.req.get_post_args
语法: args = ngx.req.get_uri_args(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*, balancer_by_lua*
接收url中的query参数,默认接受最大的参数个数是100。
语法: args, err = ngx.req.get_post_args(max_args?)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
接收POST中query参数,默认接受最大的参数个数是100。
结论:
注意Mime Type 必需是 application/x-www-form-urlencoded ,在调用该函数前必需先调用
ngx.req.read_body 或者在nginx.conf中开启 lua_need_request_body.
3.14 ngx.req.set_header、ngx.req.clear_header
语法: ngx.req.set_header(header_name, header_value)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
设置子请求的header.
ngx.req.set_header("X-Foo", nil) 等同于 ngx.req.clear_header("X-Foo")
语法: ngx.req.clear_header(header_name)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
清除子请求的header.
3.15
ngx.req.read_body、ngx.req.discard_body、ngx.req.get_body_data、ngx.req.get_body_file、ngx.req.set_body_data、ngx.req.set_body_file、ngx.req.init_body、ngx.req.append_body、ngx.req.finish_body
参考:openResty中请求体(request body)的设置与读取
3.16 ngx.req.socket
3.17 ngx.exec、ngx.redirect
语法: ngx.exec(uri, args?)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
ngx.exce仅限nginx内部跳转。
例如:
ngx.exec('/some-location'); ngx.exec('/some-location', 'a=3&b=5&c=6'); ngx.exec('/some-location?a=3&b=5', 'c=6');
例如:
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.redirect(uri, status?)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
支持内部 / 外部跳转。注意和ngx.exec的区别。
return ngx.redirect("/foo") return ngx.redirect("/foo", ngx.HTTP_MOVED_TEMPORARILY) return ngx.redirect("http://www.google.com") return ngx.redirect("/foo", 301)
3.18 ngx.send_headers、ngx.headers_sent
语法: ok, err = ngx.send_headers()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
语法: value = ngx.headers_sent
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
3.19 ngx.print、ngx.say、ngx.flush、ngx.sleep
语法: ok, err = ngx.print(…)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
语法: ok, err = ngx.say(…)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
语法: ok, err = ngx.flush(wait?)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
语法: ngx.sleep(seconds)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
3.20 ngx.exit、ngx.eof
语法: 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*
中断请求。
语法: ok, err = ngx.eof()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*
显式指定响应输出流的结束。
ngx.exit() 和 ngx.eof()的区别:
本质区别在于ngx.exit()
作用在于中断当前操作,不管是ngx-lua模块请求处理的当前阶段还是整个请求, 而ngx.eof()
只是结束响应流的输出,中断HTTP连接,后面的代码逻辑还会继续在服务端执行, 而且ngx.eof()
支持运行的上下文比ngx.exit()
少太多,ngx.eof()
有返回值,ngx.exit()
则没有,因为请求已经结束。
3.21 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*
3.22 ngx.escape_uri、ngx.unescape_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*
语法: 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*
3.23 ngx.encode_args、ngx.decode_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*
语法: 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*
3.24 ngx.encode_base64、ngx.decode_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*
语法: 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*
3.25 ngx.crc32_short、ngx.crc32_long
语法: 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*
语法: 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*
3.26 ngx.hmac_sha1、ngx.sha1_bin
语法: digest = ngx.hmac_sha1(secret_key, 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*
语法: 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*
3.27 ngx.md5、ngx.md5_bin
语法: digest = 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*
语法: digest = ngx.md5_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*
3.28 ngx.quote_sql_str
语法: quoted_value = ngx.quote_sql_str(raw_value)
作用域: 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*
3.29 ngx.is_subrequest
语法: value = ngx.is_subrequest
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
3.30 ngx.shared.DICT
用法参考:openResty中ngx.shared.DICT的用法
Pingback引用通告: openResty中ngx_lua模块提供的常量 | 精彩每一天
Pingback引用通告: openResty中ngx_lua模块提供的指令 | 精彩每一天
Pingback引用通告: openResty中的ngx.location.capture和ngx.location.capture_multi的使用 | 精彩每一天