镜像请求

镜像请求功能允许生成子请求来访问额外的服务器,实现多种业务场景。例如:

  • 向认证服务器发送请求,验证通过后再进行服务访问
  • 向 WAF 服务器发送请求,安全检查通过后再允许访问

配置参数

  • 类型:镜像请求的处理方式
    • RAW:直接镜像原始请求
    • CUSTOM:通过自定义 Lua 模块进行定制化处理
  • 模块名称:当类型为 CUSTOM 时,指定处理请求的 Lua 模块名称(模块格式要求见下文示例)
  • 上游:选择镜像请求的目标上游服务器
  • 算法:负载均衡算法,支持 Hash、Chash、Roundrobin
  • 重试次数:请求失败时的重试次数
  • 发送超时:向镜像服务器发送数据的超时时间(单位:秒)
  • 读取超时:从镜像服务器接收数据的超时时间(单位:秒)
  • 连接超时:连接镜像服务器的超时时间(单位:秒)
  • 异步:是否启用异步镜像请求(主请求无需等待子请求返回)(v25.12.1-1 新增)
  • 转发请求体:是否转发原始请求的请求体 (v25.12.1-1 新增)

注意:当上游服务器启用健康检查时,镜像请求功能将默认启用快速失败机制。这意味着当健康检查显示没有可用的上游服务器时,系统将跳过镜像请求操作。

配置示例

1. 添加全局 Lua 模块

模块代码示例:

local _M = {}

function _M.before_mirror(ctx)
    local content_length = tonumber(ngx.var.content_length)
    if content_length and ctx.max_body_size > 4096 then
        return ngx.DONE  -- 跳过镜像操作
    end
    return ngx.OK
end

function _M.mirror_rewrite(ctx)
    ngx.req.set_header('X-Real-IP', tostring(ngx.var.remote_addr))
end

function _M.mirror_header_filter(ctx)
    ngx.log(ngx.ERR, "in mirror_header_filter")
end

function _M.mirror_body_filter(ctx)
    ngx.log(ngx.ERR, "in mirror_body_filter")
end

function _M.after_mirror(ctx, resp)
    ngx.header['mirror-response-body'] = resp.body
end

function _M.header_filter()
    ngx.log(ngx.ERR, "in main request header filter")
end

function _M.body_filter()
    ngx.log(ngx.ERR, "in main request body filter")
end

return _M

回调函数说明:

  • before_mirror:子请求创建前调用,返回 ngx.DONE 可跳过镜像操作
  • mirror_rewrite:子请求 rewrite 阶段调用,可修改子请求信息
  • mirror_header_filter:子请求 header_filter 阶段调用,可修改子请求响应头
  • mirror_body_filter:子请求 body_filter 阶段调用,可修改子请求响应体(异步模式下不会调用)
  • after_mirror:子请求完成后调用(异步模式下不会调用)
  • header_filter:主请求 header_filter 阶段调用
  • body_filter:主请求 body_filter 阶段调用

2. 添加镜像服务器

3. 配置页面规则

4. 测试请求

$ curl http://test.com -v
* Rebuilt URL to: test.com/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to test.com (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: test.com
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 13 Oct 2022 08:25:22 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
< mirror-response-body: i am mirror server
< Server: openresty+
< Req-ID: 00000080000447f28b90004c
< Cache-Status: BYPASS
<
i am upstream
* Connection #0 to host test.com left intact

从响应结果可以看到,响应头中包含了 mirror-response-body: i am mirror server,说明镜像请求功能正常工作,成功获取了镜像服务器的响应内容。