前言
最近有一个需求,需要配置一个路由,这个路由是子域名形式的,域名类似 xx.apps.overstarry.vip
,我们需要根据子域名中的 xx 内容来请求同一个对象存储中不同的文件。
这个需求之前处理过,那时采用了 nginx 来处理主要路径的逻辑,apisix 直接请求 nginx 服务, 也就是大概这样的一种结构: apisix -> nginx -> oss
。这次同样的需求,我决定采用2层结构,去除中间的
nginx 层,由 apisix 直接访问 oss 服务。
接下来我就来讲述处理的过程。
过程
使用 proxy-rewrite
处理这个需求,我第一反应是使用 proxy-rewrite 插件来处理,我使用 regex_uri 字段来进行正则替换匹配,添加的插件内容如下:
"proxy-rewrite": {
"regex_uri": [
"^(.*).apps0.overstarry.vip(.*)$",
"/$1/production$2"
]
}
配置完后,请求了几次,发现没有请求成功,通过查看日志发现请求到了奇怪的地址。又仔细的研究了一会,发现是我理解错误了,proxy_rewrite 是根据 uri 进行正则匹配的,没有根据 host 匹配的选项,前面填写的那些是根本不会匹配成功的。
serverless
proxy-rewrite 插件不能实现我们的需求,我又查看了 issue列表,发现了一个issue(#7739),里面提到了可以使用插件 serverless 来实现我们的需求。
serverless 介绍
APISIX 有两个 serverless 插件:serverless-pre-function 和 serverless-post-function。
serverless-pre-function 插件会在指定阶段开始时运行,serverless-post-function 插件会在指定阶段结束时运行。这两个插件使用相同的属性。
实现
我们的需求应该是采用 serverless-pre-function 来实现,具体过程描述如下:获得请求的 host, 对 host 进行相应的文本正则替换,将替换的文本和uri 进行组合拼接,得到真正的uri.
serverless-pre-function 的函数是由 lua 编写的,由于我不会 lua, 我特地的查看了其它插件的lua代码逻辑和nginx的文档,写出了相应的代码函数:
"serverless-pre-function": {
"functions": [
"return function(conf, ctx) local uri, _, err = ngx.re.sub(ctx.var.host, \"^(.*).apps0.top007games.com(.*)$\",\"/$1/production$2\", \"jo\");ctx.var.uri = uri..ctx.var.uri ;ngx.log(ngx.ERR, \"match uri \", ctx.var.uri ); end"
],
"phase": "rewrite"
}
配置好路由插件,请求路由,成功访问了相应的对象。
小结
本文简单的介绍了如何采用 serverless-pre-function 插件编写函数来实现根据请求的路径,来访问不同的对象存储路径。
参考
- https://apisix.incubator.apache.org/zh/docs/apisix/plugins/serverless/
- https://github.com/apache/apisix/pull/8997
- https://apisix.incubator.apache.org/zh/docs/apisix/FAQ/#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F-regex-%E5%8C%B9%E9%85%8D-route-%E4%B8%AD%E7%9A%84-uri
- https://nginx.org/en/docs/varindex.html
- https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/req.md
- https://github.com/apache/apisix/blob/master/apisix/plugins/proxy-rewrite.lua
- https://github.com/apache/apisix/issues/7739