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 天前
【IoT死磕系列】Day 7:只传8字节怎么控机械臂?学习工业控制 CANopen 的“对象字典”(附企业级源码)
数据结构·stm32·物联网·http
21号 13 天前
Http粘包问题回顾
网络·网络协议·http
A懿轩A3 天前
【SpringBoot 快速开发】面向后端开发的 HTTP 协议详解:请求报文、响应码与常见设计规范
spring boot·http·设计规范
吧啦蹦吧3 天前
http-SNI
网络·网络协议·http
~kiss~4 天前
HTTP 429
网络·网络协议·http
Olive4 天前
深入理解 HTTP 请求重试:不只是指数退避那么简单
http
AI-小柒4 天前
Seedance 2.0(即梦 2.0)深度解析:AI 视频进入「导演级」可控时代
大数据·人工智能·网络协议·tcp/ip·http·音视频
弹简特4 天前
【JavaEE10-后端部分】SpringMVC05-综合案例1-从加法计算器看前后端交互:接口文档与HTTP通信详解
java·spring boot·spring·http
弹简特4 天前
【JavaEE12-后端部分】SpringMVC07-综合案例3-从留言板看前后端交互:接口文档与HTTP通信详解
spring boot·网络协议·spring·http·java-ee·交互
弹简特4 天前
【JavaEE11-后端部分】SpringMVC06-综合案例2-从用户登录看前后端交互:接口文档与HTTP通信详解
java·spring boot·spring·http·java-ee·tomcat