nginx filter分为header过滤链和body过滤链,这两天链是怎么形成的呢?在源文件ngx_http.c中,可以看到这两个函数指针变量
ngx_int_t (*ngx_http_top_header_filter)(ngx_http_request_t* r)
ngx_int_t (*ngx_http_top_body_filter)(ngx_http_request_t* r, ngx_chain_t* ch)
这是整个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;
如果仅仅写一个header filter模块,那么仅仅有ngx_http_next_header_filter
如果仅仅写一个body filter模块,那么仅仅有ngx_http_next_body_filter;
如果两条链中都有过滤,那么就都定义。
一般我们都在postconfiguration进行设置,比如ngx_http_header_filter_module
static ngx_int_t
ngx_http_header_filter_init(ngx_conf_t*cf)
{
ngx_http_top_header_filter= ngx_http_header_filter;
return NGX_OK;
}
因为配置解析完后,会遍历每一个模块的postconfiguration回调函数(针对ngx_http_header_filter_module来说,就是ngx_http_header_filter_init)。因为是依次遍历,那么这条链都是后面的模块在链表头,会先执行。
下面我们写一个filter的模块,主要功能很简单,如果content-length 超过1024字节,那么就把返回给客户端的状态码设置为404
config文件
ngx_addon_name=ngx_http_header_size_filter_module
HTTP_MODULES="$HTTP_MODULES ngx_http_header_size_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_header_size_module.c"
ngx_http_header_size_module.c文件
/*
* =====================================================================================
*
* Filename: ngx_http_header_size_module.c
*
* Description: 一个nginx filter模块,如果发送的body超过了一定大小,那么就直接设置400错误
*
* Version: 1.0
* Created: 05/04/2015 04:12:01 PM
* Revision: none
* Compiler: gcc
*
* Author: liyankun (), liyankun@baidu.com
* Organization:
*
* =====================================================================================
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
static ngx_int_t
ngx_http_header_size_filter(ngx_http_request_t *r);
static ngx_int_t
ngx_http_header_size_filter_init(ngx_conf_t* cf);
ngx_http_module_t ngx_http_header_size_filter_module_ctx = {
NULL, /* preconfiguration */
ngx_http_header_size_filter_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL, /* merge location configuration */
};
ngx_module_t ngx_http_header_size_filter_module = {
NGX_MODULE_V1,
&ngx_http_header_size_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
//定义一个static的next指针
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
//初始化函数,在配置解析完后
//此函数主要完成header函数过滤链的插入和衔接
static ngx_int_t ngx_http_header_size_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_header_size_filter;
return NGX_OK;
}
/*
* 如果说返回给用户的content_length超过1024那么就设置状态码为404
*/
static ngx_int_t
ngx_http_header_size_filter(ngx_http_request_t *r)
{
if (r->headers_out.content_length_n > 1024)
{
r->headers_out.status = NGX_HTTP_NOT_FOUND;
}
return ngx_http_next_header_filter(r);
}
模块编译
./configure --prefix=/root/hunter/nginx/ngx_gdb --with-debug --with-cc-opt='-ggdb3 -O0' --with-pcre=/root/hunter/nginx/pcre-8.36--add-module=/root/hunter/nginx/nginx-1.2.0/src/module/read_module --add-module=/root/hunter/nginx/nginx-1.
2.0/src/module/header_size
make;make install