读书人

ngxin源码分析(九)filter模块

发布时间: 2012-10-15 09:45:24 作者: rapoo

ngxin源码分析(9)——filter模块

phase handler处理中介绍了content handler用于产生响应内容,随便找一个content phase的模块,比如:ngx_http_static_module.c,会发现在content handler中会调用ngx_http_send_header,然后最后调用ngx_http_output_filter。这两个函数就是发送响应头部和响应体的,在nginx中输出内容是通过filter完成的。

filter模块用于过滤和输出响应内容,nginx将所有的filter组织成只有头结点的单链表(实际上就是栈),这个头结点分别是ngx_http_top_header_filter(过滤头部)和ngx_http_top_body_filter(过滤响应体)。在每次初始化一个filter模块时,都会将当前filter链表的头结点ngx_http_top_header_filter和ngx_http_top_body_filter分别保存为ngx_http_next_header_filter和ngx_http_next_body_filter,同时将本模块的filter函数保存为ngx_http_top_header_filter和ngx_http_top_body_filter,然后在本模块filter函数的最后部分调用ngx_http_next_header_filter和ngx_http_next_body_filter,这样就实现了所有filter模块的链式调用。由于filter模块的添加实际上就是不停的向链表的头push节点,所以后添加的模块比先添加的模块在filter链中靠前。

先看一下ngx_http_send_header函数:

    sent = c->sent;    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                   "http write filter limit %O", limit);    /* send_chain返回的是没有发完的chain */    chain = c->send_chain(c, r->out, limit);    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                   "http write filter %p", chain);    if (chain == NGX_CHAIN_ERROR) {        c->error = 1;        return NGX_ERROR;    }    /* 对limit_rate处理,可能会设置delayed标记 */    if (r->limit_rate) {        nsent = c->sent;        if (clcf->limit_rate_after) {            sent -= clcf->limit_rate_after;            if (sent < 0) {                sent = 0;            }            nsent -= clcf->limit_rate_after;            if (nsent < 0) {                nsent = 0;            }        }        delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate + 1);        if (delay > 0) {            c->write->delayed = 1;            ngx_add_timer(c->write, delay);        }    } else if (c->write->ready               && clcf->sendfile_max_chunk               && (size_t) (c->sent - sent)                      >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)    {        c->write->delayed = 1;        ngx_add_timer(c->write, 1);    }    /* 释放已经发送的chain的内存 */    for (cl = r->out; cl && cl != chain; /* void */) {        ln = cl;        cl = cl->next;        ngx_free_chain(r->pool, ln);    }    /* 重新赋值尚未发送的chain */    r->out = chain;    /* 如果chain不为空,那么buf没有发送完,需要设置buffered标记,并返回NGX_AGAIN */    if (chain) {        c->buffered |= NGX_HTTP_WRITE_BUFFERED;        return NGX_AGAIN;    }    /* 如果已经没有未发送的chain,就情况buffered标记 */    c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;    /* 如果其他filter模块buffer了chain并且postponed为NULL,那么返回NGX_AGAIN,需要继续处理buf */    if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) {        return NGX_AGAIN;    }    return NGX_OK;
上面就是ngx_http_write_filter的处理过程,ngx_http_header_filter与之类似,只是它处理的是响应头,然后在最后也是通过ngx_http_write_filter输出。





读书人网 >编程

热点推荐