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
相关推荐
阑梦清川3 小时前
JavaEE初阶---网络原理(五)---HTTP协议
网络·http·java-ee
阿尔帕兹4 小时前
构建 HTTP 服务端与 Docker 镜像:从开发到测试
网络协议·http·docker
follycat7 小时前
[极客大挑战 2019]HTTP 1
网络·网络协议·http·网络安全
earthzhang20217 小时前
《深入浅出HTTPS》读书笔记(5):随机数
网络协议·http·https
xiaoxiongip6667 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
CXDNW8 小时前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
城南vision9 小时前
计算机网络——HTTP篇
网络协议·计算机网络·http
‍。。。11 小时前
使用Rust实现http/https正向代理
http·https·rust
红黑色的圣西罗21 小时前
Lua 怎么解决闭包内存泄漏问题
开发语言·lua
田三番1 天前
使用 vscode 简单配置 ESP32 连接 Wi-Fi 每日定时发送 HTTP 和 HTTPS 请求
单片机·物联网·http·https·嵌入式·esp32·sntp