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
相关推荐
审判长烧鸡10 小时前
标准 HTTP API 签名鉴权 Header 完整规范
http·web
00后程序员张15 小时前
HTTPS单向认证、双向认证、抓包原理与反抓包策略详解
网络协议·http·ios·小程序·https·uni-app·iphone
June bug15 小时前
Failed to fetch+HTTP 422=Agent ID 不匹配
网络·网络协议·http
minji...18 小时前
Linux 网络基础之传输层协议TCP(九)从内核源码的角度打通系统与网络之间的关系,套接字多态的体现
linux·运维·服务器·网络·网络协议·tcp/ip·http
想唱rap19 小时前
IO多路转接之epoll
linux·运维·服务器·数据库·网络协议·算法·http
十五年专注C++开发19 小时前
QHttp: 一个开源的轻量级、异步、高性能 HTTP 库
c++·qt·网络协议·http·qhttp
minji...19 小时前
Linux 网络基础之传输层协议TCP(八)拥塞控制,延迟应答,捎带应答,TCP粘包问题,异常退出问题
linux·服务器·网络·网络协议·tcp/ip·http·智能路由器
野熊佩骑2 天前
一文读懂Nginx 之 Ubuntu使用apt方式安装Nginx官方最新版本
linux·运维·服务器·nginx·ubuntu·http
minji...2 天前
Linux 网络基础之传输层TCP(七)确认应答机制,超时重传机制,连接管理机制(三次握手四次挥手),流量控制,滑动窗口,快重传
linux·运维·服务器·网络·网络协议·tcp/ip·http
专吃海绵宝宝菠萝屋的派大星2 天前
spring Ai 开发的mcp-由sse改成Streamable HTTP
人工智能·spring·http