关于老板让我用 Openresty 实现的各种奇怪需求以及实现
本文主要介绍最近整理的用Openresty
处理的一些需求或功能,当然这都是领导时不时给我提出来需求,有些需求个人感觉还是怪怪的,不过领导的话不能不听不是?
关于Openresty
网上有很多介绍,他的普通用法和Nginx
几乎一样没什么特别的。高级功能的话,Openresty
比Nginx
支持更多的模块,还支持Lua
、JavaScript
作为脚本语言实现更高级的功能。
需求一、URL 重写
这个需求还算比较常见,就是把一个 url 转换成另一种形式,举个例子:
领导:你来把
https://www.example.com/article/xxxxx
这个 url 给我转后端的https://www.example.com/api/article/xxxxx
一个接口上。我:为啥不直接请求后端接口?
领导:
/api/
一看就是后端接口,要让用户看起来像是直接访问一个页面。
这个小需求可以直接用rewrite
实现,先看下rewrite
的用法:
rewrite
其中最后一个参数:
last
: 表示在匹配完本条规则后还会继续向下找其他 location;break
:表示匹配完本条规则后就直接返回;redirect
:会返回 302 临时重定向,地址栏的地址会发生变化,爬虫不会更新 url。permanent
:会返回 301 永久重定向,地址栏的地址会发生变化,爬虫会更新 url。
需求实现
我只要拿到 uri,因为前缀是一样的,所以只需要把 uri 后面的 xxxxx 解析出来就好了,rewrite
之后,直接break
。直接在server
块里加上下面这块代码,轻轻松松实现。
需求二、URL 重写+参数名转换
这个需求,跟上一个基本类型,只是多了一个参数转变的过程。
领导:你来把
https://www.example.com/article/xxxxx?id=yyyyy
这个 url 给我转后端的https://www.example.com/api/article/xxxxx
一个接口上,然后把 id 这个参数给我变成articleId
。我:直接用
articleId
不行吗?领导:不行。
好吧,继续干活,这个需求可以分为两步,第一步把url
用rewrite
重写和上面的一样,第二步把参数换一个名字。
参数获取
在 nginx 中可以使用$arg_XXX
来获取请求的参数,例如https://www.example.com/article/xxxxx?id=yyyyy
这个请求,在 nginx 中可以直接使用$arg_id
获取id
这个参数。
需求实现
知道怎么拿到参数后,实现就简单了,在第一示例的代码基础上改改就可以了。
需求三、域名过滤
这个需求是说,服务器接收好多请求,这些请求有不同的域名,要过滤需要的域名请求。
领导:咱们目前的服务器是别的组不用的,现在还有其他域名请求会进来,你判断下如果是咱们的域名就继续执行,如果不是咱们的,直接返回 404。
我:哦。
if AND OR 判断
这个需求理解是如果是A域名
或者是B域名
,请求继续,如果都不是则返回 404,但 nginx 虽然支持if判断
,但是并不支持AND
、 OR
这样的操作,只能换一种方式实现。
实现思路为:我设置一个字符串,如果不是A域名
我追加一个字符,如果不是B域名
我再追加一个字符,如果这个字符串为等于一个值那么就返回 404。
需求实现
刚才已经分析完了,直接上代码吧,在server
块里,加上下面这个代码即可。
需求四、配置 CORS 指定 Origin
这个需求是跨域设置,不能设置为*
,只允许特定的域名请求,添加信任域名。
领导:给咱们网站接口设置下允许哪些域名可以访问。
我:你后端不能做吗?
领导:后端还不得写代码吗。
我:。。。。。。
map 指令
这个map
的含义简单理解为,map
匹配一个字符串作为key
,按照映射关系把value
的值赋值给$variable
这个变量。
需求实现
既然不能用*
设置允许所有跨域访问,只能定义一个白名单了,最终实现如下:
需求五、参数值转换
这天领导又给我来了个震惊我的需求:把一个请求的参数值按照一定的规则动态换成数据库里的另一个值。
领导:你看这个
url
,https://www.example.com/api/user/info?openId=xxxx
,在 Openresty 中把这个 openId 给我换成数据库里的主键 id,然后用 id 参数传给我,就是变为https://www.example.com/api/user/info?id=yyyy
。我:你没开玩笑?
领导:我像在开玩笑吗?下午给我。
解决思路
既然没开玩笑,那就想办法呗。用Openresty
连数据库?额,不太好。
从官网找了找,也没有找到好办法,那只能写个脚本了。
先判断是这个url
,先内部发送个请求根据openId
查询对应id
,再把id
拼接到url
继续处理后续逻辑。
需求实现
先写个lua
脚本,从脚本中根据openId
查询出对应id
是多少,然后再把 id 参数拼接上,重新请求接口。
相当于中间经过了一层中转,因为是服务内部请求,所以性能影响不是很大,来看下代码实现。
lua 脚本 user_api.lua
openresty
配置如下,需要加上access_by_lua_file
,对应的值为 lua 脚本的路径。
后记
这些都是领导提出的一些需求,你以为就这些吗?不不不,这只是冰山一角,后续会再介绍其他需求,以及解决方案。
评论