openresty开发系列33--openresty执行流程之2重写赋值阶段

一)重写赋值阶段

1)set_by_lua

语法:set_by_lua $res <lua-script-str> [$arg1 $arg2 …]
语境:server、server if、location、location if
阶段:rewrite

设置nginx变量,我们用的set指令即使配合if指令也很难实现负责的赋值逻辑;

传入参数到指定的lua脚本代码中执行,并得到返回值到res中。
<lua-script-str>中的代码可以使从ngx.arg表中取得输入参数(顺序索引从1开始)。

这个指令是为了执行短期、快速运行的代码因为运行过程中nginx的事件处理循环是处于阻塞状态的。
耗费时间的代码应该被避免。
禁止在这个阶段使用下面的API:
1、output api(ngx.say和ngx.send_headers);
2、control api(ngx.exit);
3、subrequest api(ngx.location.capture和ngx.location.capture_multi);
4、cosocket api(ngx.socket.tcp和ngx.req.socket);
5、sleep api(ngx.sleep)

a、nginx.conf配置文件

location /lua {
    set $jump "1";
    echo $jump;
}

set 命令对变量进行赋值,但有些场景的赋值业务比较复杂,需要用到lua脚本
所以用到set_by_lua

b、补充知识点:

ngx.var.arg与ngx.req.get_uri_args的区别,都是能够获取请求参数

ngx.var.arg_xx与ngx.req.get_uri_args["xx"]两者都是为了获取请求uri中的参数
例如 http://pureage.info?strider=1
为了获取输入参数strider,以下两种方法都可以:

local strider = ngx.var.arg_strider

local strider = ngx.req.get_uri_args["strider"]

差别在于,当请求uri中有多个同名参数时,ngx.var.arg_xx的做法是取第一个出现的值
ngx.req_get_uri_args["xx"]的做法是返回一个table,该table里存放了该参数的所有值

例如,当请求uri为:http://pureage.info?strider=1&strider=2&strider=3&strider=4时

ngx.var.arg_strider的值为"1",而ngx.req.get_uri_args["strider"]的值为table ["1", "2", "3", "4"]。
因此,ngx.req.get_uri_args属于ngx.var.arg_的增强。

-------------------------------
案例需求:书店网站改造把之前的skuid为8位商品,请求到以前的页面,为9位的请求到新的页面
书的商品详情页进行了改造,美化了一下;上线了时候,不要一下子切换美化页面;;做AB概念
把新录入的书的商品 采用 新的商品详情页,之前维护的书的商品详情页 用老的页面

以前书的id 为8位,新的书id为9位

root /data/www/html;

location /book {

set_by_lua $to_type '
                        local skuid = ngx.var.arg_skuid
                        ngx.log(ngx.ERR,"skuid=",skuid)
                        local r = ngx.re.match(skuid, "^[0-9]{8}$")
                        local k = ngx.re.match(skuid, "^[0-9]{9}$")
                        if r then
                                return "1"
                        end;
                        if k then
                                return "2"
                        end;
                ';

if ($to_type = "1") {
                        echo "skuid为8位";
                        proxy_pass http://127.0.0.1/old_book/$arg_skuid.html;
                }
                if ($to_type = "2") {
                        echo "skuid为9位";
                        proxy_pass http://127.0.0.1/new_book/$arg_skuid.html;
                }

}

# 具体的网页内容
[root@node5 data]# tree /data/www/html/
/data/www/html/
├── new_book
│   └── 123456789.html
└── old_book
    └── 12345678.html

2 directories, 2 files
[root@node5 data]# cat /data/www/html/old_book/12345678.html
<h1>old book</h1>
[root@node5 data]# cat /data/www/html/new_book/123456789.html
<h1>new book</h1>

# 测试访问:http://10.11.0.215/book?skuid=123456789
会跳转到new_book/123456789.html

访问:http://10.11.0.215/book?skuid=12345678
会跳转到new_book/12345678.html

=======================================

2)set_by_lua_file

语法set_by_lua_file $var lua_file arg1 arg2...;

在lua代码中可以实现所有复杂的逻辑,但是要执行速度很快,不要阻塞;

location /lua_set_1 {
    default_type "text/html";
    set_by_lua_file $num /usr/local/luajit/test_set_1.lua;
    echo $num;
}

2.1、test_set_1.lua

local uri_args = ngx.req.get_uri_args()
local i = uri_args["i"] or 0
local j = uri_args["j"] or 0

return i + j

得到请求参数进行相加然后返回。

访问如http://192.168.31.138/lua_set_1?i=1&j=10进行测试。 如果我们用纯set指令是无法实现的。

3)注意,这个指令只能一次写出一个nginx变量,但是使用ngx.var接口可以解决这个问题:

location /foo {
    set $diff '';
    set_by_lua $sum '
        local a = 32
        local b = 56
        ngx.var.diff = a - b; --写入$diff中
        return a + b;  --返回到$sum中
    ';
    echo "sum = $sum, diff = $diff";
}

openresty开发系列33--openresty执行流程之2重写赋值阶段的更多相关文章

  1. openresty开发系列36--openresty执行流程之6日志模块处理阶段

    openresty开发系列36--openresty执行流程之6日志模块处理阶段 一)header_filter_by_lua 语法:header_filter_by_lua <lua-scri ...

  2. openresty开发系列35--openresty执行流程之5内容content阶段

    openresty开发系列35--openresty执行流程之5内容content阶段 content 阶段 ---init阶段---重写赋值---重写rewrite---access content ...

  3. openresty开发系列34--openresty执行流程之4访问阶段

    openresty开发系列34--openresty执行流程之4访问阶段 访问阶段 用途:访问权限限制 返回403 nginx:allow 允许,deny 禁止 allow ip:deny ip: 涉 ...

  4. openresty开发系列33--openresty执行流程之3重写rewrite和重定向

    openresty开发系列33--openresty执行流程之3重写rewrite和重定向 重写rewrite阶段 1)重定向2)内部,伪静态 先介绍一下if,rewrite指令 一)if指令语法:i ...

  5. openresty开发系列32--openresty执行流程之1初始化阶段

    openresty开发系列32--openresty执行流程之初始化阶段 一)初始化阶段 1)init_by_lua   init_by_lua_block     init_by_lua_file语 ...

  6. openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息

    openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息 为了实现业务系统针对不同地区IP访问,展示包含不同地区信息的业务交互界面.很多情况下系统需要根据用户访问的IP信息 ...

  7. openresty开发系列38--通过Lua+Redis 实现动态封禁IP

    openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...

  8. openresty开发系列37--nginx-lua-redis实现访问频率控制

    openresty开发系列37--nginx-lua-redis实现访问频率控制 一)需求背景 在高并发场景下为了防止某个访问ip访问的频率过高,有时候会需要控制用户的访问频次在openresty中, ...

  9. openresty开发系列31--openresty执行流程

    openresty开发系列31--openresty执行流程 我们先看个例子 location /test {    set $a 32;    echo $a;    set $a 56;    e ...

随机推荐

  1. windows10访问ftp中文乱码怎么办?

    windows10访问ftp中文乱码怎么办? 打开控制面板 选择时间和区域 选择更改数字格式 点击管理并点击更改系统区域设置 打勾

  2. 微信小程序~下拉刷新真机测试不弹回的处理办法

    问题描述: 下拉刷新在手机上不会自动回弹,开发工具可以 解决办法: 主动调用wx.stopPullDownRefresh /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDow ...

  3. 关于srping的AOP事务管理问题,自定义切面是否导致事务控制失效

    applicationContext.xml: <!-- 方法调用时间记录 --> <bean id="methodExecuteTime" class=&quo ...

  4. c和c++区别(未整理)

    学习完C语言和c++比较一下他们之间的区别: c++是c语言的基础上开发的一种面向对象的编程语言,应用十分广泛,按理说c++可以编译任何c的程序,但是两者还是有细微的差别. c++在c的基础上添加了类 ...

  5. Python基础初始之二

    1.格式化的输出 当你遇到这样的需要:字符串中想让某些位置变成动态可传入的,首先考虑用格式化输出 1.格式化输出:% 2. 格式化输出:format 3. 格式化输出:f 2.运算符 3.编码 待续

  6. MSSQL行车列规则

    行转列,是SQL中经常会遇到的一个问题,并且分为静态转换和动态转换,所谓静态转换即在转换的行数已知或固定:动态转换则为转换的行数不固定. 转换的方法一般采用case when语句或pivot(MSSQ ...

  7. Mysql 多表连接查询 inner join 和 outer join 的使用

    JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. 首先先列举本篇用到的分类(内连接,外连接,交 ...

  8. javascript中的indexOf与if判断的装逼写法

    常规indexOf与if判断写法: if("112233".indexOf("22")>-1) { console.log("很二") ...

  9. vue-cli3整体迁移至服务端渲染nuxtjs

    vue项目与nuxt.js实在有着太多的不同,例如项目结构变化很大,router.js没了,vuex store写法有变化,router钩子没了等等.老项目毕竟也有一些体量,这么折腾我可接受不了,不过 ...

  10. 洛谷P4408 逃学的小孩

    题目 求树的直径,因为任意两个居住点之间有且只有一条通路,所以这是一棵树. 根据题意父母先从C去A,再去B,或者反过来. 我们一定是要让A到B最大,也要让C到A和B的最小值最大. AB最大一定就是直径 ...