1 nginx过滤模块简介
过滤(filter)模块是过滤响应头和内容的模块,可以对回复的头和内容进行处理。它的处理时间在获取回复内容之后,向用户发送响应之前。它的处理过程分为两个阶段,过滤HTTP回复的头部和主体,在这两个阶段可以分别对头部和主体进行修改。
2 过滤模块执行顺序
2.1 ngx_http_output_(head, body)_filter_pt
先看一下nginx常用的过滤模块,在ngx_moudles.c中有一下代码:
ngx_module_t *ngx_modules[] = {
......
&ngx_http_write_filter_module,
&ngx_http_header_filter_module,
&ngx_http_chunked_filter_module,
&ngx_http_range_header_filter_module,
&ngx_http_gzip_filter_module,
&ngx_http_postpone_filter_module,
&ngx_http_ssi_filter_module,
&ngx_http_charset_filter_module,
&ngx_http_userid_filter_module,
&ngx_http_myfilter_module,
&ngx_http_headers_filter_module,
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
nginx过滤模块的执行顺序是从ngx_http_not_modified_filter_module 到 ngx_http_write_filter_module。下面我们来看一下这个执行顺序是怎么用链表构成的。
既然是用链表构成的,肯定是要有链表指针,而且有两个,一个链接处理头部的函数,一个链接处理包体的函数,下面来看看这两个链表指针的定义:
typedef ngx_int_t (ngx_http_output_header_filter_pt)(ngx_http_request_t *r);
typedef ngx_int_t (ngx_http_output_body_filter_pt)(ngx_http_request_t *r, ngx_chain_t *in);
ngx_http_output_header_filter_pt 指向处理头部的函数指针,每一个过滤模块中如果要处理头部,就必要定义一个局部的这种类型的指针和函数。
ngx_http_output_body_filter_pt 指向处理包体的函数指针,每一个过滤模块中如果要处理包体,就必要定义一个局部的这种类型的指针和函数。
2.2 过滤模块链表的入口
过滤模块链表的入口是两个静态的函数指针:
extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;
extern ngx_http_output_body_filter_pt ngx_http_body_body_filter;
当执行ngx_http_send_header发送http头部时,就开始从ngx_http_tou_header_filter指针遍历所有的http头部过滤模块。
ngx_http_send_header:
ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
if (r->err_status) {
r->headers_out.status = r->err_status;
r->headers_out.status_line.len = 0;
}
return ngx_http_top_header_filter(r);//链表头,指向第一个过滤头部的模块函数
}
当执行ngx_http_output_filter发送包体时,就从ngx_http_top_body_filter指针遍历所有的http包体过滤模块。
ngx_http_output_filter:
ngx_int_t
ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_int_t rc;
ngx_connection_t *c;
c = r->connection;
rc = ngx_http_top_body_filter(r, in);
if (rc == NGX_ERROR) {
c->error = 1;
}
return rc;//链表头ÿ