nginx模块:捕获整个响应体

nginx模块:捕获整个响应体,nginx,filter,module,buffer,Nginx,Filter,Module,Buffer,尽管Nginx是一款非常有趣的软件,但缺少文档让我抓狂 目标:捕获整个响应主体,该主体将被记录到服务器上 问题:我总是有一个大小为零的缓冲区 方法 我希望能够使用一个,在迭代整个缓冲区链之前“等待”最后一个buf来完成这个需求 /** * @param ngx_http_request_t *r HTTP request * @param ngx_chain_t *in Buffer chain */ static ngx_int_t c

尽管Nginx是一款非常有趣的软件,但缺少文档让我抓狂

目标:捕获整个响应主体,该主体将被记录到服务器上

问题:我总是有一个大小为零的缓冲区

方法

我希望能够使用一个,在迭代整个缓冲区链之前“等待”最后一个buf来完成这个需求

/**
 * @param   ngx_http_request_t     *r     HTTP request
 * @param   ngx_chain_t            *in    Buffer chain
 */
static ngx_int_t
create_response_snapshot(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_chain_t *chain = NULL;
    int chain_contains_last_buffer = 0;
    size_t buffer_size = 0;

    // check if body is complete
    chain = in;
    for ( ; ; )
    {
        if (chain->buf->last_buf)
        {
            chain_contains_last_buffer = 1;
        }

        if (NULL == chain->next)
            break;

        chain = chain->next;
    }

    if (0 == chain_contains_last_buffer)
    {
        // response is not complete
        return ngx_http_next_body_filter(r, in);
    }

    // Response Content-Length
    ngx_log_error(NGX_LOG_ALERT,r->connection->log,0,"Content-Length: %d",
                  r->headers_out.content_length_n);

    // lets iterate buffers chain
    for (chain = in; NULL != chain; chain = chain->next)
    {
        buffer_size = ngx_buf_size(chain->buf);
        ngx_log_error(NGX_LOG_ALERT,r->connection->log,0,"buffer_size#%d",buffer_size);
    }

    return ngx_http_next_body_filter(r, in);
}

我的评论太大了,不能作为评论,但我觉得这不是一个正确的答案——哦,好吧

要重新迭代,您发布的代码的问题是,不会在整个链上同时调用模块的body filter函数。它在第一个片段上被调用,然后在第二个片段上被调用,直到第n个片段。最后,它会在一个完全空的链上被调用,无论出于什么原因,
last\u buf=1
的buf总是自己空的

因此,我认为您要做的是通过在模块中累积缓冲区来“拦截”缓冲区流,而不向下一个过滤器释放任何缓冲区,直到您同时拥有所有缓冲区

查看替代过滤器模块:

它使用了一个“忙”链,这正是我所指的。据我所知,它使用它来跟踪实际发送了哪些缓冲区(当这种情况发生时,大小设置为零),并将这些缓冲区添加到模块上下文的空闲列表中以供重用。有关此行为,请参阅第438行的ngx_http_sub_输出


我的建议是做一些类似于模块所做的事情,除了在获得整个页面之前不调用下一个过滤器。如果要将整个页面作为一个整体进行处理,则不能调用next_filter,因为这样做将导致数据被发送到客户端。同样,这与Nginx的设计背道而驰,因此我认为,如果可以的话,您应该找到一种不需要立即提交整个响应正文的替代方案。

缺少文档也让我抓狂!我找到的唯一指南(Evan Miller的)并没有开始解释大多数
ngx_,而是
成员的目的。我认为在这种情况下,您需要不断将
in
链添加到模块上下文的
busy
成员中,直到获得最后一个buf。这是因为你的过滤器被调用了很多次,包含
last\u buf
的过滤器是最后一个调用,它总是与我所看到的内容相隔离。哦,如果你没有得到最后一个链,你可能会返回
NGX\u OK
而不是调用
NGX\u http\u next\u body\u filter
。然后将整个链条一次传递到其余的过滤器。基本上,您正在删除Nginx以块的形式处理输出的功能,这有点违背了这一点。@GVH“我认为在这种情况下,您需要继续将in-chain添加到模块上下文的繁忙成员中,直到获得最后一个buf”。你能解释一下“忙碌的成员”吗。我不知道它应该是什么。关于返回“NGX_OK”,根据Evan Miler的教程,每个过滤器负责调用下一个过滤器。我将深入研究其他模块。