场景
如果Kong前端uris配置正则表达式,虽然Kong能够捕获正则表达式的值,但是它不会用该值去替换上游upstream_url里面预设变量,例如:
前端uris配置
1 | /api/testmap/(?<id>\d+) |
上游upstream_url配置类似这样
1 | http://192.168.1.3:10000/api/testmap/{id} |
前端发起请求
1 | curl http://10.0.0.111/api/testmap/1/ |
上游upstream_url的值都是
1 | http://192.168.1.3:10000/api/testmap/{id} |
解决思路
既然Kong能够捕获正则表达式的值,只需要用Kong捕获的值,对upstream_url进行正则替换即可。
获取
如果,Kong前端uris配置为
1 | /api/testmap/(?<id>\d+) |
那么,Kong将捕获的值,以table类型存储在变量ngx.ctx.router_matches.uri_captures
中。
如果,前端发起的请求为
1 | curl http://10.0.0.111/api/testmap/2/ |
那么ngx.ctx.router_matches.uri_captures
变量的值为
1 | {"2", id = "2"} |
需要注意的是,如果uris里面没有正则表达式,那么变量ngx.ctx.router_matches.uri_captures
的值为nil
,而不是一个table
。
替换
定义upstream_url里面的变量时候,需要有一定的特征。
例如,uris定义为
1 | /api/testmap/(?<id>\d+) |
那么,upstream_url定义的时候,就将id
用特需符号标识,比如用{}
来标识这是一个待替换的变量
1 | http://192.168.1.3:10000/api/testmap/{id} |
做一个table
的循环,k
是待替换的变量,v
是最后替换的值。
1 | for k, v in pairs(uri_captures) do |
重置
变量替换好后,需要重置upstream_uri
的值。有个坑就是,Kong版本大于等于0.11.0
后,不支持用ngx.req.set_uri()
重置upstream_uri
的值,需要用ngx.var.upstream_uri
重置upstream_uri
。
官方更新日志是这么说的:
The upstream URI is now determined via the Nginx $upstream_uri variable. Custom plugins using the ngx.req.set_uri() API will not be taken into consideration anymore. One must now set the ngx.var.upstream_uri variable from the Lua land.
代码
插件的核心代码handler.lua
1 | local BasePlugin = require "kong.plugins.base_plugin" |
该插件也适用于uris包含多个正则表达式的场景。
插件GitHub开源地址kong-plugin-upstream-url-penetrate