执行时间和内容
过滤(filter)模块是过滤响应头和内容的模块,可以对回复的头和内容进行处理。它的处理时间在获取回复内容之后,向用户发送响应之前。它的处理过程分为两个阶段,过滤HTTP回复的头部和主体,在这两个阶段可以分别对头部和主体进行修改。
在代码中有类似的函数:
ngx_http_top_header_filter(r);
ngx_http_top_body_filter(r, in);
就是分别对头部和主体进行过滤的函数。所有模块的响应内容要返回给客户端,都必须调用这两个接口。
执行顺序
过滤模块的调用是有顺序的,它的顺序在编译的时候就决定了。控制编译的脚本位于auto/modules中,当你编译完Nginx以后,可以在objs目录下面看到一个ngx_modules.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_headers_filter_module,
&ngx_http_copy_filter_module,
&ngx_http_range_body_filter_module,
&ngx_http_not_modified_filter_module,
NULL
};
从write_filter到not_modified_filter,模块的执行顺序是反向的。也就是说最早执行的是not_modified_filter,然后各个模块依次执行。所有第三方的模块只能加入到copy_filter和headers_filter模块之间执行。
Nginx执行的时候是怎么按照次序依次来执行各个过滤模块呢?它采用了一种很隐晦的方法,即通过局部的全局变量。比如,在每个filter模块,很可能看到如下代码:
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
...
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_example_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_example_body_filter;
ngx_http_top_header_filter
是一个全局变量。当编译进一个filter模块的时候,就被赋值为当前filter模块的处理函数。而 ngx_http_next_header_filter
是一个局部全局变量,它保存了编译前上一个filter模块的处理函数。所以整体看来,就像用全局变量组成的一条单向链表。
每个模块想执行下一个过滤函数,只要调用一下 ngx_http_next_header_filter
这个局部变量。而整个过滤模块链的入口,需要调用 ngx_http_top_header_filter
这个全局变量。ngx_http_top_body_filter
的行为与header fitler类似。
响应头和响应体过滤函数的执行顺序如下所示:
这图只表示了head_filter和body_filter之间的执行顺序,在header_filter和body_filter处理函数之间,在body_filter处理函数之间,可能还有其他执行代码。
模块编译
Nginx可以方便的加入第三方的过滤模块。在过滤模块的目录里,首先需要加入config文件,文件的内容如下:
ngx_addon_name=ngx_http_example_filter_module
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_example_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_example_filter_module.c"
说明把这个名为 ngx_http_example_filter_module
的过滤模块加入, ngx_http_example_filter_module.c
是该模块的源代码。
注意 HTTP_AUX_FILTER_MODULES
这个变量与一般的内容处理模块不同。