Nginx学习—http过滤模块
Posted 孙飞 Sunface
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx学习—http过滤模块相关的知识,希望对你有一定的参考价值。
HTTP过滤模块
为什么要使用过滤模块
HTTP过滤模块本质上也是一种HTTP模块,因此整个开发过程跟之前的《 Hello Nginx!》是相似的。不同的是,过滤模块所做的工作只是对发送给用户的HTTP响应包做一些加工。 HTTP框架为HTTP请求的处理过程定义了11个阶段,相关代码: [cpp] view plain copy- 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模块处理请求完毕,开始发送HTTP头或包体时,才开始依次调用过滤模块处理请求,因此,HTTP过滤模块只处理服务器发往客户端的响应,不处理客户端发往服务器的请求;
过滤模块顺序
在编译nginx源码时,我们知道在ngx_modules.c文件中已经定义了一个模块数组,这个数组其实也就暗含了过滤模块的调用顺序。过滤链表
所有HTTP过滤模块会构成一个单链表,链表的每一个元素都是一个独立的.c源文件。这个.c源文件会通过两个static静态指针(分别用于HTTP头和包体)指向下一个.c源文件。在ngx_http.c中定义两个指针,指向整个链表的首元素,也即第一个处理HTTP头和包体的方法。 [cpp] view plain copy- 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 ngx_http_output_header_filter_pt ngx_http_next_header_filter;
- static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
- 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_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);
过滤链表顺序
还是在编译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学习—http过滤模块的主要内容,如果未能解决你的问题,请参考以下文章
Nginx防盗链模块ngx_http_referer_module