应用场景:
用户请求想要生产的流量打到原有服务的同时,打到新开发的服务上试一下
注意的点:
1 nginx是不读请求体的,需要在配置文件中打开,或者读取前调用ngx.req.read_body(),然后通过local data = ngx.req.get_body_data()获取
2 header转发时如果原请求里有"accept-encoding"这样支持压缩的声明返回的是二进制,记录日志不方便读取要单独处理下
-- mirror.lua
local core = require("apisix.core")
local http = require("resty.http")
local json = require("apisix.core.json")local plugin_name = "mirror"local schema = {type = "object",properties = {uri = {type = "string",},serviceHost = {type = "string",},serviceName = {type = "string",},method = {type = "string",enum = {"POST", "GET"},default = "POST"},timeout = {type = "number",default = 3000},},
}local _M = {version = 0.1,priority = 98,name = plugin_name,schema = schema,
}function _M.check_schema(conf)local ok, errok, err = core.schema.check(schema, conf)if not ok thenreturn false, errendif not conf.serviceHost thenconf.serviceHost = conf.serviceNameendif conf.timeout < 0 thenconf.timeout = 5 * 1000endreturn true
end-- timeout in ms
local function http_req(method, uri, body, myheaders, timeout)local httpc = http.new()if timeout thenhttpc:set_timeout(timeout)endmyheaders["accept-encoding"] = nilcore.log.info("Mirrored request http uri ", uri," method ", method)core.log.info("Mirrored request http header ", core.json.delay_encode(myheaders))core.log.info("Mirrored request http req param ", core.json.delay_encode(body))local res, err = httpc:request_uri(uri, {method = method,body = body,headers = myheaders,ssl_verify = false})core.log.info("Mirrored request http status ", res.status)core.log.info("Mirrored request http body ", res.body)return res
endfunction _M.access(conf, ctx)core.log.info("Mirrored request start ")ngx.req.read_body()local data = ngx.req.get_body_data()local req_headers = ngx.req.get_headers()req_headers["Host"] = conf.servicHostcore.log.info("Mirrored request conf ", core.json.delay_encode(conf))local method = conf.methodif not method or method == nil or method == "" thenmethod = ngx.req.get_method()endlocal url = conf.serviceNameif not conf.uri or conf.uri == nil or conf.uri == "" thenurl = url .. ngx.var.urielseurl = url .. conf.uriendlocal args, err = ngx.req.get_uri_args()if G thenlocal first = truefor key, val in pairs(args) doif first thenurl = url .. "?"first = falseelseurl = url .. "&"endurl = url .. key .. "=" .. valendendlocal res,err = http_req(method, url, data, req_headers, conf.timeout)core.log.info("Mirrored request end")
endreturn _M