前言

最近有一个需求,需要配置一个路由,这个路由是子域名形式的,域名类似 xx.apps.overstarry.vip,我们需要根据子域名中的 xx 内容来请求同一个对象存储中不同的文件。

这个需求之前处理过,那时采用了 nginx 来处理主要路径的逻辑,apisix 直接请求 nginx 服务, 也就是大概这样的一种结构: apisix -> nginx -> oss。这次同样的需求,我决定采用2层结构,去除中间的 nginx 层,由 apisix 直接访问 oss 服务。

接下来我就来讲述处理的过程。

过程

使用 proxy-rewrite

处理这个需求,我第一反应是使用 proxy-rewrite 插件来处理,我使用 regex_uri 字段来进行正则替换匹配,添加的插件内容如下:

1
2
3
4
5
6
 "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的文档,写出了相应的代码函数:

1
2
3
4
5
6
"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 插件编写函数来实现根据请求的路径,来访问不同的对象存储路径。

参考