openresty中ngx_lua模块提供的api | 落井下石


本站和网页 http://www.hangdaowangluo.com/archives/2694 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

openResty中ngx_lua模块提供的API | 落井下石
落井下石 小树苗似得一天天成长 --> 菜单 跳至内容 首页 网络服务 Apache vsftpd Http Nginx Tomcat DNS 数据库 MySQL mongodb PostgreSQL MariaDB 操作系统 Linux Shell Docker 分布式集群 Redis CODIS ZOOKEEPER Hadoop Kafka RabbitMQ beanstalkd
ElasticSearch
Vagrant
大数据
Hbase
数据挖掘
配置管理
Git
Gerrit
GitLab
Jira
NGrinder
开发语言
C/C++
Go
lumen
PHP
Javascript
yaf
angular
nodeJs
css3
html5
workerman
OpenResty
微信小程序
算法
架构
HAProxy
Laravel
Lua
keepalived
composer
网络架构
硬件
AI
读书笔记
MySQL5.7中文手册
计算机组成与设计
openResty中ngx_lua模块提供的API
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:
三、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
sub post:
location /main {
content_by_lua_block {
ngx.ctx.blah = 73
main pre:
local res = ngx.location.capture("
") //发起新的子请求
ngx.print(res.body)
main post:
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
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.
示例:
header
content_type
text/plain
; --等于 ngx.header["Content-Type"] = 'text/plain'
X-My-Header
blah blah
; --等于 ngx.header.x_my_header = 'blah blah'
删除示例:
nil
{};
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: */*
headers = ngx.req.get_headers(max_headers?, raw?)
获取请求头部信息,返回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)
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)
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
Host:xopen.100.com:8080
User-Agent:curl/7.43.0
Accept:*/*
3.7 ngx.req.is_internal
is_internal = ngx.req.is_internal()
判断是否nginx内部跳转,等于 false表示为外部请求。
3.8 ngx.req.start_time
secs = ngx.req.start_time()
计算请求的执行时间,可以模拟nginx中的
$request_time
ngx.update_time()
local
request_time
now
()
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
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
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()
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()
返回请求协议的版本。
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)
设置
请求的方法。注意参数是method的id,即必须使用ngx.HTTP_GET、ngx.HTTP_POST设置,具体可参考:
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_uri
/foo
true
相当于 rewrite
last
false
/foo break;
相当于 ngx.
/test
rewrite_by_lua_block
uri = ngx.re.sub(ngx.var.uri,
"^/test/(.*)"
"/
$1
"o"
ngx.req.set_uri(uri)
proxy_pass
http://my_backend;
rewrite
/foo?a=3?
相当于
ngx.req.set_uri_args("a=3")
ngx.req.set_uri("/foo", true)
ngx.req.set_uri_args({
= 3})
 示例:
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")
local args = ngx.req.get_uri_args()
for k, v in pairs(args) do
ngx.say(k,":",v)
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$
rewrite ^/case\.html$
/vcase.php
rewrite ^/case/([0-9a-zA-Z]+)\.html$
/vcase.php?iid=$1
rewrite ^/mobile\.html$
/vmobile.php
rewrite ^/email\.html$
/vemail.php
rewrite ^/mail\.html$
/vmail.php
rewrite ^/mail/([0-9a-zA-Z]+)\.html$
/vmail.php?iid=$1
rewrite ^/hosting\.html$
/vhosting.php
rewrite ^/flow\.html$
/vflow.php
rewrite ^/news\.html$
/vnews.php
rewrite ^/news/([0-9a-zA-Z]+)/?$
/vnews.php?do=$1
rewrite ^/news/([0-9a-zA-Z]+)/([0-9a-zA-Z]+)\.html$
/vnews.php?do=$1&iid=$2
使用ngx_lua替换:
local rules = {
["^/$"]
= "/php/index.php",
["^/index.html$"]
["^/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
if replaceUri ~= "" then
local splits = string:split(replaceUri, "?")
if splits[2] then
ngx.req.set_uri_args(splits[2])
ngx.req.set_uri(splits[1],true)
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?)
接收url中的query参数,默认接受最大的参数个数是100。
args, err = ngx.req.get_post_args(max_args?)
接收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)
设置子请求的header.
set_header
X-Foo
等同于
clear_header
ngx.req.clear_header(header_name)
清除子请求的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
openResty中cosocket的控制
3.17 ngx.exec、ngx.redirect
ngx.exec(uri, args?)
ngx.exce仅限nginx内部跳转。
exec
/some-location
);
a=3&b=5&c=6
/some-location?a=3&b=5
c=6
 例如:
ngx.exec("@bar", "a=goodbye");
@bar
args = ngx.req.get_uri_args()
for
key, val in pairs(args) do
if
key ==
"a"
then
ngx.say(val)
ngx.redirect(uri, status?)
支持内部 / 外部跳转。注意和ngx.exec的区别。
return
redirect
, ngx.
HTTP_MOVED_TEMPORARILY
http://www.google.com
301
3.18 ngx.send_headers、ngx.headers_sent
ok, err = ngx.send_headers()
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(…)
ok, err = ngx.say(…)
ok, err = ngx.flush(wait?)
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()
显式指定响应输出流的结束。
ngx.exit() 和 ngx.eof()的区别:
本质区别在于
ngx.exit()
作用在于中断当前操作,不管是ngx-lua模块请求处理的当前阶段还是整个请求,
ngx.eof()
只是结束响应流的输出,中断HTTP连接,后面的代码逻辑还会继续在服务端执行,
而且
支持运行的上下文比
ngx.exit()
少太多,
有返回值,
则没有,因为请求已经结束。
3.21 ngx.log
ngx.log(log_level, …)
3.22 ngx.escape_uri、ngx.unescape_uri
newstr = ngx.escape_uri(str)
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?)
newstr = ngx.decode_base64(str)
3.25 ngx.crc32_short、ngx.crc32_long
intval = ngx.crc32_short(str)
intval = ngx.crc32_long(str)
3.26 ngx.hmac_sha1、ngx.sha1_bin
digest = ngx.hmac_sha1(secret_key, str)
digest = ngx.sha1_bin(str)
3.27 ngx.md5、ngx.md5_bin
digest = ngx.md5(str)
digest = ngx.md5_bin(str)
3.28 ngx.quote_sql_str
quoted_value = ngx.quote_sql_str(raw_value)
3.29 ngx.is_subrequest
value = ngx.is_subrequest
3.30 ngx.shared.DICT
用法参考:
openResty中ngx.shared.DICT的用法
 
本条目发布于
2017年11月27日
。属于
分类,被贴了
lua
openresty
标签。
作者是
admin
entry-meta -->
文章导航
上一篇:
下一篇:
》上有3条评论
Pingback引用通告:
openResty中ngx_lua模块提供的常量 | 精彩每一天
openResty中ngx_lua模块提供的指令 | 精彩每一天
openResty中的ngx.location.capture和ngx.location.capture_multi的使用 | 精彩每一天
发表评论
取消回复
电子邮件地址不会被公开。
必填项已用
标注
姓名
电子邮件
站点
评论
您可以使用这些
HTML
标签和属性:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
搜索:
angularJs
Bind
Codis
Es
ETL
Js
kafka
liunx
LVS
Mysql
vagrant
Vsftp
Yaf
Yum
Zookeeper
规划师
近期文章
一些图片
Openai的模型有哪些?
OpenAi官方提供的模型有哪些?
了解AI相关的概念一篇就够了
golang的命令行操作
计算机组成与设计-指令:计算机语言
计算机组成与设计:硬件_软件接口中文答案(第一章)
计算机组成与设计-计算机概要与技术
Prometheus中文文档
操作系统中的一些概念
动态规划
优秀程序设计的Kiss原则
理解二叉树的四种遍历-前序、中序、后序、层序
GO中参数传递的理解
GO中值交换的原理
递归算法满足的三个条件
链表操作练习题
数据结构与算法-数组 & 链表
认识时间复杂度与空间复杂度
锁机制及CAS实现原理
常见开源OLAP技术架构对比
ETL与大数据是什么关系?
设计模式
Workerman-高性能socket服务框架
Kubernetes文档
一文带你读懂CNCF Landscape
一张图搞懂head -n和tail -n
C语言学习笔记 – 编程基础
C语言学习笔记(一)
Yaf可选的配置项
Yaf运行时配置
PHP配置指令作用域说明
Yaf的安装
常见数据结构与算法整理总结(下)
常见数据结构与算法整理总结(上)
Nginx、LVS、HAProxy负载均衡软件的优缺点详解
TCP和UDP的区别[经典]
保证分布式系统数据一致性的6种方案
系统架构设计理论与原则
如何选择并落地架构方案的?
float与double的范围和精度
C代码到可执行文件的过程
使用C语言的7个步骤
openResty中获取请求 body
openResty学习中的知识点(一)
openResty的安装配置详解
Beanstalkd中文协议
查看linux中的TCP连接
BeansTalkd的命令
BeansTalkd的使用与安装
Redis中的Lua脚本
[转]理解OAuth 2.0
PostgreSQL中的系统环境变量
PostgreSQL的pg_hba.conf 客户端认证
微信小程序的app.json配置
MySQL 5.7 的新特性
MySQL的特性
MySQL的安装与配置
MariaDB的安装与配置
PostgreSQL与Mysql的不同之处
PostgreSQL的安装与配置
Go中的net/url包学习笔记
Go中net包中的方法
如何优雅地关闭Go channel
Goroutine Channel Select 的用法和理解
Goroutine和channel的详细理解(三)
Goroutine和channel的详细理解(二)
Goroutine和channel的详细理解(一)
Go新建文件权限与设置不符
Go中的os包之目录和文件(file)的操作
GO中new 和 make的区别
GO中断言interface类型的方法
Docker资源管理探秘-Cgroups机制
C语言中内存堆和栈的区别
Docker的内核知识之Namespace资源隔离
Docker的内核知识之cgroups资源限制
Docker 资源(cpu、memory)限制实践篇
Docker create / Docker run 的选项详解
Docker的实践笔记
Docker network的网络特性
Docker中的镜像构建-Dockerfile指令详解
Docker的命令之快捷指令
Docker的命令之数据卷管理 Volume
Docker的命令之系统管理 Docker system
Docker的命令之集群管理 swarm
Docker的命令之 Docker stacks
Docker的命令之集群服务管理 Service
Docker的命令之安全管理 Docker secret
Docker的命令之插件管理 Plugin
Docker的命令之集群节点管理 Swarm node
Docker的命令之网络管理 network
Docker的命令之镜像管理 Image
Docker的命令之容器管理 Container
文章归档
2023年十一月
2023年五月
2023年四月
2022年十月
2021年十二月
2021年九月
2021年五月
2021年四月
2021年三月
2020年十一月
2020年八月
2020年六月
2019年一月
2018年九月
2018年二月
2018年一月
2017年十二月
2017年十一月
2017年十月
2017年九月
2017年八月
2017年七月
2017年六月
2017年五月
2017年四月
2017年三月
2017年二月
2017年一月
2016年十二月
2016年十一月
2016年十月
2016年九月
2016年八月
2016年六月
2016年五月
2016年四月
2016年三月
2016年二月
2016年一月
2015年十二月
2015年九月
2015年八月
2015年七月
2015年三月
备案号:
冀ICP备14002216号-1