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
相关推荐
yanlou23313 小时前
[C++/Linux HTTP项目] HTTP服务器基于muduo高性能服务器搭载【深入详解】
运维·服务器·http·muduo库·http高性能服务器
不许哈哈哈14 小时前
HTTP协议基础(运维开发面试版)
http·面试·运维开发
王锋(oxwangfeng)15 小时前
Nginx 四层 TCP 与七层 HTTP 转发实战指南
tcp/ip·nginx·http
码农水水16 小时前
传音Java面试被问:HTTP/2的多路复用和头部压缩实现
java·开发语言·spring boot·后端·http·面试·职场和发展
她说..17 小时前
Java Web 开发:请求头、请求体、响应体 数据获取全攻略(附实战示例)
java·开发语言·spring boot·spring·http·spring mvc
奋斗者1号17 小时前
【MCP深度解析】Stdio vs SSE vs Streamable HTTP:三大通信机制全景对比与选型指南
网络·网络协议·http
宁雨桥17 小时前
HTTP 协议全景解析:无状态、明文与安全演进之路
网络协议·安全·http
zhaotiannuo_19981 天前
渗透测试之HTTP\HTTPS协议和BP抓包
网络协议·http·https
zzu123zsw1 天前
Chisel 实战指南:一条命令打通 HTTP 隧道
网络·网络协议·http
Julian.zhou1 天前
HTTP/1.1到HTTP/3全面演进指南:收益、实战成本与迁移策略
网络·网络协议·http