Mirror Request

This function provides a way to generate sub-requests to access additional servers. For example, you can send a request to the authentication server and access the service after the authentication is passed; you can also send a request to the WAF server and access it after the WAF authentication is passed.

  • Type: the way to mirror the request; RAW: mirror the actual request directly; CUSTOM: do some custom processing.
  • Module Name: When the type is CUSTOM, you need to specify the Lua module that will handle the request. This Lua module needs to have a specific format, which will be described later.
  • Upstream: select which upstream server to mirror the request to.
  • Algorithm: load balancing algorithm, optional: Hash, Chash, Roundrobin.
  • Retry times: the number of retries after a failed request.
  • Send timeout: timeout for sending data to the mirror server in seconds.
  • Read timeout: timeout to receive data from the mirror server in seconds.
  • Connect timeout: timeout to connect to the mirror server in seconds.

In addition, if the upstream health check is enabled, the mirror request feature will fail fast by default, which means that no mirror request will be attempted when no upstream server is available for the health check.

Example

Add Global Lua Module

The code is as follows:

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: called before the child request is generated. The method returns ngx.DONE indicating an immediate return and no mirroring is performed.
  • mirror_rewrite: called during the rewrite phase of the subrequest and can be used to modify the information of the subrequest.
  • mirror_header_filter: called during the header_filter phase of the subrequest and can be used to modify the response headers of the subrequest.
  • mirror_body_filter: called at the body_filter stage of the subrequest, can be used to modify the response body of the subrequest.
  • after_mirror: called after the subrequest returns.
  • header_filter:called during the main request header filter phase.
  • body_filter:called during the main request body filter phase.

Add Mirror Server

Configure Page Rules

Send Request

$ 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

As you can see, the response header contains mirror-response-body: i am mirror server.