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 (), [email protected]
* 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