apisix http请求转发插件by lua

应用场景:

用户请求想要生产的流量打到原有服务的同时,打到新开发的服务上试一下

注意的点:

1 nginx是不读请求体的,需要在配置文件中打开,或者读取前调用ngx.req.read_body(),然后通过local data = ngx.req.get_body_data()获取

2 header转发时如果原请求里有"accept-encoding"这样支持压缩的声明返回的是二进制,记录日志不方便读取要单独处理下

Lua 复制代码
-- 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, err
    ok, err = core.schema.check(schema, conf)
    if not ok then
        return false, err
    end
    if not conf.serviceHost then
        conf.serviceHost = conf.serviceName
    end
    if conf.timeout < 0 then
        conf.timeout = 5 * 1000
    end
    return true
end


-- timeout in ms
local function http_req(method, uri, body, myheaders, timeout)
    local httpc = http.new()
    if timeout then
        httpc:set_timeout(timeout)
    end
    myheaders["accept-encoding"] = nil
    core.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
end





function _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.servicHost
    core.log.info("Mirrored request conf ",  core.json.delay_encode(conf))
    local method = conf.method
    if not method or method == nil or method == "" then
        method = ngx.req.get_method()
    end
    local url = conf.serviceName
    if not conf.uri or conf.uri == nil or conf.uri == "" then
        url = url .. ngx.var.uri
    else
        url = url .. conf.uri
    end
    local args, err = ngx.req.get_uri_args()
    if G then
        local first = true
        for key, val in pairs(args) do
            if first then
                url = url .. "?"
                first = false
            else
                url = url .. "&"
            end
            url = url .. key .. "=" .. val
        end
    end
    local res,err = http_req(method, url, data, req_headers, conf.timeout)
    core.log.info("Mirrored request end")
end

return _M
相关推荐
ftpeak18 小时前
从零开始使用 axum-server 构建 HTTP/HTTPS 服务
网络·http·https·rust·web·web app
java搬砖工-苤-初心不变1 天前
基于 lua_shared_dict 的本地内存限流实现
开发语言·junit·lua
程序猿多布1 天前
XLua教程之热补丁技术
unity·c#·lua·xlua
java搬砖工-苤-初心不变1 天前
OpenResty 限流方案对比:lua_shared_dict vs Redis
redis·lua·openresty
weixin_456904271 天前
使用HTTPS 服务在浏览器端使用摄像头的方式解析
网络协议·http·https
程序猿多布1 天前
XLua教程之Lua调用C#
unity·c#·lua·xlua
拷贝码农卡卡东2 天前
pre-commit run --all-files 报错:http.client.RemoteDisconnected
网络·网络协议·http
又菜又爱玩呜呜呜~2 天前
go使用反射获取http.Request参数到结构体
开发语言·http·golang
夜猫逐梦2 天前
【Lua】Windows 下编写 C 扩展模块:VS 编译与 Lua 调用全流程
c语言·windows·lua
cellurw2 天前
Linux下C语言实现HTTP+SQLite3电子元器件查询系统
linux·c语言·http