huzilinitachi的专栏

blog of jerrylining

nginx http处理(postpone延迟处理过滤器)

        ngx_http_postpone_filter_module 用于处理延时的http请求(主要是子请求配置的)。postpone过滤器发生的时间点在处理响应包体时,这也是这个模块名称的由来。延时处理过滤功能和子请求之间的联系在点击打开链接子请求的说明里。

        postpone的处理流程也比较简单:先配置top_body_filter处理函数指针,然后再通过配置的函数处理发生作用。

        第一步,先配置top_body_filter处理函数 这个函数会在处理响应包体时发生作用,body_filter并非只有一个函数,而是通过设置top_body_filter来形成一个链式的处理结构,不同的body_filter的区别在于函数挂载的先后次序,先挂载的先处理,后挂载的后处理。

        第二步,通过配置的top_body_filter函数对响应包体的内容进行处理,如果存在postpone待处理的请求,进行必要的设置及处理的工作,下面以代码的处理流程作为说明。

static ngx_int_t
ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
{

    ...
    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                   "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
    /*connection中保存的数据不是当前的请求*/
    if (r != c->data) {

        if (in) {  /* 待处理的buffer链是有效的 会将当前的http请求增加到postpone链表中 并将in的链表拷贝到postpone中
                    */
            if (ngx_http_postpone_filter_add(r, in) != NGX_OK) {
                return NGX_ERROR;
            }   /*由于connection中保存的数据不是当前的请求 直接返回*/
            return NGX_OK;
        }

#if 0
        /* TODO: SSI may pass NULL */
        ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                      "http postpone filter NULL inactive request");
#endif

        return NGX_OK;
    }

    if (r->postponed == NULL) {
       /*如果请求的postponed链表是空的 说明不需要进行postpone处理 直接交由后一个body_filter处理即可*/
        if (in || c->buffered) {
            return ngx_http_next_body_filter(r->main, in);
        }

        return NGX_OK;
    }

    if (in) {   /*把in拷贝到postpone中 并加入到postponed链表*/
        if (ngx_http_postpone_filter_add(r, in) != NGX_OK) {
            return NGX_ERROR;
        }
    }

    do {  /*正式处理postponed链表 */
        pr = r->postponed;

        if (pr->request) {
          /*postpone存在请求 先将postponed处理切换到当前的postpone下一个*/
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                           "http postpone filter wake \"%V?%V\"",
                           &pr->request->uri, &pr->request->args);

            r->postponed = pr->next;

            c->data = pr->request;
            /*将当前的postpone中保存的请求提交到主请求的posted_request链表中 这里处理完一个就直接返回了*/
            return ngx_http_post_request(pr->request, NULL);
        }

        if (pr->out == NULL) {   /*发现postpone响应buffer链是空的 报错*/
            ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                          "http postpone filter NULL output");

        } else {   /*postpone响应buffer链是有效的 将其交予下一个body_filter进行处理*/
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                           "http postpone filter output \"%V?%V\"",
                           &r->uri, &r->args);

            if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
                return NGX_ERROR;
            }
        }
        /*postponed遍历至下一个*/
        r->postponed = pr->next;

    } while (r->postponed);

    return NGX_OK;
}

   ngx_http_postponed_request_t 结构加入到http请求的postponed链表中

static ngx_int_t
ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_http_postponed_request_t  *pr, **ppr;

    if (r->postponed) {  /*请求的postponed链表是存在的 遍历到最后一个*/
        for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }

        if (pr->request == NULL) { /*postpone中保存的请求是无效的 直接使用*/
            goto found;
        }

        ppr = &pr->next;

    } else {   /*请求的postponed链表是无效的 作为第一个即可*/
        ppr = &r->postponed;
    }
    /*为新的postpone分配空间*/
    pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
    if (pr == NULL) {
        return NGX_ERROR;
    }
    /*设置到postponed链表中*/
    *ppr = pr;
    /*必要的初始化*/
    pr->request = NULL;
    pr->out = NULL;
    pr->next = NULL;

found:
    /*拷贝in的buffer链内容到postpone响应buffer链中*/
    if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) {
        return NGX_OK;
    }

    return NGX_ERROR;
}

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huzilinitachi/article/details/79976845
上一篇nginx 处理http(发送http响应头数据篇 ----- ngx_http_header_filter_module模块处理)
下一篇nginx http处理(write_filter响应数据发送过滤器)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭