百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Nginx Lua编程-简单案例 nginx+lua

liebian365 2024-11-14 18:02 19 浏览 0 评论

案例一:Lua脚本获取URL中的参数

  • 通过ngx_lua模块的内置方法ngx.req.get_uri_args()获取URL后面的请求参数
  • 通过Nginx内置变量$arg_PARAMETER获取请求参数的值
#ngx.req.get_uri_args()方法Lua脚本获取URL中的参数
location /add_params_demo {
	set_by_lua	$sum	'
		local args = ngx.req.get_uri_args();
		local a = args["a"];
		local b = args["b"];
		return a + b;
	';
echo "$arg_a + $arg_b = $sum";
}

#ngx.arg获取请求参数值
location /add_params_demo_2 {
	set_by_lua	$sum	'
		local a = tonumber(ngx.arg[1]);
		local b = tonumber(ngx.arg[2]);
		return a + b;
	'	$arg_a $arg_b;
	echo "$arg_a + $arg_b = $sum";
}

Nginx Lua的内置方法

Nginx Lua的内置方法

方法说明

ngx.log(log_lever, ...)

按照log_level设定的等级输出到error.log日志文件

Pring(...)

输出到error.log日志文件,等价于ngx.log(ngx.NOTICE, ...)

ngx.print(...)

输出响应内容到客户端

ngx.say(...)

输出响应内容到客户端,自动添加'\n'换行符

ngx.exit(status)

如果status>=200,此方法就会结束当前请求处理,并且返回status状态码到客户端;若status==0,此方法就会结束请求处理的当前阶段,进入下一个请求处理阶段

ngx.send_header()

显示地发送响应头

ngx.exec(uri, args?)

内跳转URI地址

ngx.redirect(uri,status?)

外部跳转URI地址

ngx.location.capture(uri, options?)

发起一个子请求

ngx.location.capture_multi(uris)

发起多个子请求。参数uris是一个table,格式为{{uri, options?},{uri, options?},...}

ngx.is_subrequest()

当前请求是不是子请求

ngx.sleep(seconds)

无阻塞休眠秒数(定时器实现)

ngx.get_phase()

获取当前Lua脚本的执行阶段名称。

ngx.req.start_time()

请求开始时间

ngx.req.http_version()

请求的HTTP版本号

ngx.req.raw_header

获取原始的请求头(包括请求行)

ngx.req.get_method()

获取请求方法

ngx.req.set_method(method)

覆盖当前的请求方法

ngx.req.get_uri_args()

获取请求参数

ngx.req.get_post_args()

获取post请求内容,调用此方法之前必须调用ngx.req.read_body()来读取body体

ngx.req.get_headers()

默认获取前100个请求头

ngx.resp.get_headers()

获取响应头

ngx.req.read_body()

获取当前请求的请求体

ngx.req.set_header(name, value)

为当前请求设置请求头

ngx.req.clear_header(name)

为当前请求删除名称为name的请求头

ngx.req.set_body_data(data)

设置当前请求的请求体为data

ngx.req.init_body(buffer_size?)

为当前请求创建一个空的请求体。如果buffer_size参数不为空,那么新请求体的大小为buffer_size。若为空,那么新请求体的大小为client_body_buffer_size指令设置的请求体大小。若未设置,默认大小为8KB(32位系统、x86-64)或者16KB(其他的64位系统)

ngx.escape_uri(str)

对uri字符串进行编码

ngx.unescape_uri(str)

对编码过的URL字符串进行解码

ngx.encode_args(table)

将Lua table编码为一个参数字符串

ngx.decode_args(str)

将参数字符串解码为一个Lua table

ngx.encode_base64(str)

将字符串str编码成base64摘要

ngx.decode_base64(str)

将base64摘要解码成原始字符串

ngx.hmac_sha1(secret, str)

将字符串str编码成二进制格式的hmac_sha1,并使用secret进行加密

ngx.md5(str)

将字符串str编码成十六进制MD5摘要

ngx.md5_bin(str)

将字符串str编码成二进制的MD5摘要

ngx.quote_sql_str(str)

SQL语句转译,按照MySQL的格式进行转义

ngx.today()

获取当前日期

ngx.time()

获取UNIX时间戳

ngx.now()

获取当前时间

ngx.update_time()

刷新时间后再返回

ngx.localtime()

获取yyyy-mm-dd hh:mm:ss格式的本地时间

ngx.cookie_time()

获取可用于cookie值的时间

ngx.http_time()

获取可用于HTTP头的时间

ngx.parse_http_time()

解析HTTP头的时间

ngx.config.nginx_version()

获取Nginx版本号

ngx.config.ngx_lua_version()

获取ngx_lua模块版本号

ngx.worker.pid()

获取当前Worker进程的pid

案例二:通过ngx.header设置HTTP响应头

ngx_lua模块可以通过内置变量ngx.header来访问和设置HTTP响应头字段,ngx.header的类型为table,可以通过ngx.header.HEADER形式应用某个响应头。

例如:使用ngx.header.set_cookie变量设置响应头set-cookie的值,使用table类型的对象可以一次设置多个set-cookie值。

#模拟上游服务
location /header_demo {
	content_by_lua_block {
  	ngx.header["header1"] = "value1";
    ngx.header.header2 = 2;
    ngx.header.set_cookie = {'Foo=bar; test=ok; path=/','age=18; path=/'};
    ngx.say("演示程序: ngx.header的使用");
  }
}

#模拟网关反向代理
location /header_filter_demo {
	proxy_pass http://127.0.0.1/header_demo;

  header_filter_by_lua_block {
  	local cookies = ngx.header.set_cookie;
  	if cookies then
      if type(cookies) == "table" then
      	local cookie = {}
    		for k, v in pairs(cookies) do
      		cookie[k]= v..";Secure;httponly"
      	end
      	ngx.header.set_cookie = cookie
      else
      	ngx.header.set_cookie = cookies..";Secure;httponly"
      end
    end
  }
}

响应结果如下


Cookie是通过请求的set-cookie响应头来保存的,HTTP响应内容中可以包含多个set-cookie响应头,一个set-cookie响应头的值通常为一个字符串。该字符串大致包含如下Cookie信息或属性

  • Cookie名称:只能使用可以用于URL中的字符,一般为字母和数字,不能包含特殊字符,否则需要转码。
  • Cookie值: 同Cookie名称。
  • expires: Cookie过期日期。
  • path: Cookie的访问路径。此属性设置指定路径下的页面才可以访问该Cookie。访问路径的值一般设为“/”。
  • domain: Cookie的访问域名。此属性设置指定域名下的页面才可以访问该Cookie。
  • Secure: Cookie的安全属性,此属性设置该Cookie是否只能通过HTTPS协议访问。只有值,没有名称。
  • HttpOnly: 如果设置了该属性,那么通过程序将无法读取到Cookie信息。只有值,没有名称。

当设置了HttpOnly属性时,通过脚本将无法获取到Cookie信息,主要用于防止XSS攻击。

而一旦设置了Secure属性,前后端之间只能在HTTPS协议通信的情况下,浏览器才能访问Cookie,使用HTTP协议时,浏览器无法获取Cookie信息,同样是对Cookie信息的保护。通常都是在内网环境继续使用HTTP通信协议,然后通过Nginx网关完成外部HTTPS协议到内部HTTP协议的转换。此时,Nginx外部网关可以对Cookie属性进行修改,增加Secure安全属性。

案例三:Lua访问Nginx变量

无论是Nginx内部变量还是自定义变量,都可以在Lua代码中通过ngx.var进行访问。

#通过ngx.var访问Nginx变量
location /lua_var_demo {
  
	#自定义Nginx变量,名为hello,值为world
  set $hello world;

  content_by_lua_block {
  	local basic = require("conf.luaScript.module.common.basic");
    
    --定义一个Lua table,暂存需要输出的Nginx内置变量
    local vars = {};
    
    vars.remote_addr = ngx.var.remote_addr;
    vars.request_uri = ngx.var.request_uri;
    vars.query_string = ngx.var.query_string;
    vars.uri = ngx.var.uri;

    vars.nginx_version = ngx.var.nginx_version;
    vars.server_protocol = ngx.var.server_protocol;
    vars.request_method = ngx.var.request_method;
    vars.request_filename = ngx.var.request_filename;
    vars.document_root = ngx.var.document_root;
    vars.body_bytes_sent = ngx.var.body_bytes_sent;
    vars.binary_remote_addr = ngx.var.binary_remote_addr;
    vars.args = ngx.var.args;

    --通过内置变量访问请求参数
    vars.foo = ngx.var.arg_foo;
    ngx.say("演示程序: 将内置变量返回给客户端<br>");
    --使用自定义函数将Lua table转换成字符串,然后输出
    local str = basic.tableToStr(vars, ",<br>");
    ngx.say(str);

    ngx.say("<br>演示程序: 将普通变量返回给客户端<br>");
    --访问自定义Nginx变量hello
    local hello = ngx.var.hello;
    ngx.say("hello = "..hello);
  } 	
}

重启OpenResty后,浏览器访问http://localhost/lua_var_demo

案例四:Lua访问请求上下文变量

Nginx执行Lua脚本涉及很多阶段,每个阶段都可以嵌入不同的Lua脚本,不同阶段的Lua脚本可以通过ngx.ctx进行上下文变量共享。ngx.ctx上下文实质上是一个Lua table,其生存周期与当前请求相同,当前请求不同阶段嵌入的Lua脚本都可以读写ngx.ctx表中的属性。这些属性可以在请求处理的rewrite、access、content等各处理阶段进行共享。另外,在ngx_lua模块中,每个请求,包括子请求,都有一份独立的ngx.ctx表。

演示示例

#Lua访问请求上下文变量
location /ctx_demo {
	rewrite_by_lua_block {
  	-- 在上下文设置属性var1
   	ngx.ctx.var1 = 1;
  }

  access_by_lua_block {
  	-- 在上下文设置属性var2
    ngx.ctx.var2 = 10;
  }

  content_by_lua_block {
    local basic = require("conf.luaScript.module.common.basic");
   	-- 在上下文设置属性var3
    ngx.ctx.var3 = 100;

    -- 3个上下文求和
    local result = ngx.ctx.var1 + ngx.ctx.var2 + ngx.ctx.var3;
    ngx.say(result);

    ngx.ctx.sum = result;

    -- 使用自定义函数将Lua table转换成字符串
    local str = basic.tableToStr(ngx.ctx, ",<br>");
    ngx.say("<br>");
    ngx.say(str);
  }
}

运行结果:

下一篇介绍复杂案例!

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: