镜像请求

此功能提供了一个生成子请求来访问额外的服务器的途径。例如,可以通过此功能发送请求到认证服务器,认证通过了再进行服务访问;也可以通过此功能发送请求到 WAF 服务器,WAF 验证通过后再进行访问。

  • 类型:镜像请求的方式。RAW:直接镜像原始请求;CUSTOM:进行一些定制处理。
  • 模块名称:类型为 CUSTOM 时需要指定处理请求的 Lua 模块。此 Lua 模块需要有特定格式,将在后面介绍。
  • 上游:选择镜像请求到哪个上游服务器。
  • 算法:负载均衡算法,可选:Hash、Chash、Roundrobin。
  • 重试次数:请求失败后的重试次数。
  • 发送超时:发送数据到镜像服务器的超时时间,单位:秒。
  • 读取超时:从镜像服务器接收数据的超时时间,单位:秒。
  • 链接超时:连接到镜像服务器的超时时间,单位:秒。

此外,如果上游开启了健康检查,镜像请求功能将会默认快速失败,这意味着当健康检查没有上游服务器可用时,将不尝试进行镜像请求。

示例

添加全局 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_body_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 阶段调用。

添加镜像服务器

配置页面规则

发送请求

$ curl 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