Nginx学习(7)—http过滤模块(1)
2014-04-28 11:59
381 查看
HTTP过滤模块
为什么要使用过滤模块
HTTP过滤模块本质上也是一种HTTP模块,因此整个开发过程跟之前的《Hello Nginx!》是相似的。不同的是,过滤模块所做的工作只是对发送给用户的HTTP响应包做一些加工。HTTP框架为HTTP请求的处理过程定义了11个阶段,相关代码:
[cpp] view
plaincopy
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE, // 大部分HTTP模块只在此阶段处理
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
一般而言,普通HTTP模块倾向于完成请求的核心功能(如static模块负责静态文件处理),而HTTP过滤模块则负责处理一些附加功能(如gzip压缩)。
过滤模块特性:
过滤模块效果可以根据需要叠加;
普通HTTP模块处理请求完毕,开始发送HTTP头或包体时,才开始依次调用过滤模块处理请求,因此,HTTP过滤模块只处理服务器发往客户端的响应,不处理客户端发往服务器的请求;
过滤模块顺序
在编译Nginx源码时,我们知道在ngx_modules.c文件中已经定义了一个模块数组,这个数组其实也就暗含了过滤模块的调用顺序。过滤链表
所有HTTP过滤模块会构成一个单链表,链表的每一个元素都是一个独立的.c源文件。这个.c源文件会通过两个static静态指针(分别用于HTTP头和包体)指向下一个.c源文件。在ngx_http.c中定义两个指针,指向整个链表的首元素,也即第一个处理HTTP头和包体的方法。[cpp] view
plaincopy
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 *chain);
extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;
extern ngx_http_output_body_filter_pt ngx_http_top_body_filter;
然后,在每一个过滤模块做初始化工作时,会先找到链表当前的首元素,然后再使用本身的static静态类型指针:
[cpp] view
plaincopy
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
将自己插入到链表首部,源码实现如下:
[cpp] view
plaincopy
static ngx_int_t
ngx_http_XXX_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_XXX_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_XXX_body_filter;
return NGX_OK;
}
当执行ngx_http_send_header发送HTTP头时,就开始遍历所有HTTP头部过滤模块了。
[cpp] view
plaincopy
ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
if (r->header_sent) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"header already sent");
return NGX_ERROR;
}
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);
}
HTTP包体链表类似。
过滤链表顺序
还是在编译Nginx源码时,编译进的ngx_modules.c模块数组,这个数组其实也就暗含了过滤模块的调用顺序。首先,这个数组保存了所有的Nginx模块,包括HTTP普通模块与过滤模块,因此在初始化模块的顺序就按照这个该数组的成员顺序。又因为每个过滤模块都会将自己的初始化方法插入链表首部,因此过滤模块的调用顺序应该是数组中所有过滤模块的反向。具体的,结合书中内容,如下图:
过滤模块开发步骤
步骤基本与普通HTTP模块开发一致,概括总结如下:增加.c源码文件;(HTTP过滤模块功能单一,一般一个.c文件即实现一个HTTP过滤模块)
在源码文件所在目录下创建config脚本文件,以便执行configure命令时将模块编译进Nginx;(与普通模块的config文件唯一不同就是HTTP_MODULES替换成HTTP_FILTER_MODULES)
定义过滤模块,即实例化ngx_module_t类型结构;
处理感兴趣的配置项,即设置ngx_command_t类型结构;
实现初始化方法,即插入单链表首部;
实现处理HTTP头部的方法;
实现处理HTTP包体的方法;
编译安装,修改nginx.conf文件并启动自定义过滤模块。
相关文章推荐
- Nginx学习(7)—http过滤模块(2)
- 【 nginx模块学习】nginx_http_push_module模块深入讲解和聊天室实现
- nginx模块学习七 http_refer 防盗链
- nginx图片过滤处理模块http_image_filter_module安装配置笔记
- Nginx HttpSubModule sub_filter模块的过滤功能
- Nginx基础. HTTP过滤模块添加方式探讨
- 【Nginx】开发一个HTTP过滤模块
- nginx模块学习一 http_stub_status_module 客户端连接状态
- Nginx开发一个简单的HTTP过滤模块
- nginx http core模块学习
- nginx模块学习三 http_auth_basic_module 访问身份证验证
- Nginx HTTP过滤模块开发
- nginx模块学习——nginx_http_push_module模块深入讲解和聊天室实现
- nginx开发学习——过滤模块
- nginx模块学习——nginx_http_push_module模块深入讲解和聊天室实现
- nginx图片过滤处理模块http_image_filter_module安装配置笔记
- 【Nginx】开发一个HTTP过滤模块
- nginx模块学习——nginx_http_push_module模块深入讲解和聊天室实现
- 【nginx源码学习与运用 十】第二个http模块——发送磁盘文件