简单的http过滤模块

来源:互联网 发布:用java开发apk的步骤 编辑:程序博客网 时间:2024/05/21 08:47

http过滤模块仅处理服务器发往客户端的http响应,不处理客户端发往服务器的http请求。

过滤模块的调用顺序

过滤链表

在编译nginx源码时,已经定义了一个由所有http过滤模块组成的单链表(每个元素都是一个独立的c源码文件。这个文件会通过两个static指针指向下一个文件中的过滤方法)

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); //chain表示要发送的包体

http框架中定义的链表入口

extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;extern ngx_http_body_header_filter_pt ngx_http_top_body_filter;

过滤链表的顺序

每个http过滤模块的初始化方法都会把自己加入到单链表的首部
大多数官方http过滤模块都会把初始化方法放到postconfiguration指针中
这里写图片描述

http过滤模块的开发步骤

  1. 确定源代码文件名称
  2. 在源代码所在目录创建config脚本文件,在执行configure时将该目录添加进去。HTTP_FILTER_MODULES,当使用多个源代码文件实现1个http过滤模块时,需要在NGX_ADDON_SRCS变量中添加其他源代码文件
  3. 定义过滤模块。
  4. 处理感兴趣的配置项。
  5. 实现初始化方法。初始化方法就是把本模块中处理http头部的ngx_http_output_header_filter_pt和处理http包体的ngx_http_output_body_filter_pt方法插入到过滤模块链表的首部
  6. 实现处理http头部的方法
  7. 实现处理http包体的方法
  8. 编译安装,修改nginx.conf文件并启动自定义过滤模块

http过滤模块的简单例子

在返回包体前加一段字符串 “[my fiter prefix]”
这里写图片描述
这里写图片描述

编写config文件

使用一个源文件实现此功能,源文件名为:ngx_http_myfilter_module.c
在该文件所在目录添加config文件:

ngx_addon_name=ngx_http_myfilter_moduleHTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_myfilter_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_myfilter_module.c"

配置项和上下文

首先,希望在nginx.conf中有一个控制当前http过滤模块是否生效的配置项 参数为on | off。建立ngx_http_myfilter_conf_t结构体来存储配置项,使用ngx_flag_t类型的enable变量来存储这个参数值

typedef struct{    ngx_flag_t enable;}ngx_http_myfilter_conf_t;

下面的ngx_http_myfilter_create_conf用于分配存储配置项的结构体ngx_http_myfilter_conf_t;

static void* ngx_http_myfilter_create_conf(ngx_conf_t *cf){    ngx_http_myfilter_conf_t *mycf;    //创建存储配置项的结构体    mycf=(ngx_http_myfilter_conf_t *)ngx_pcalloc(cf->pool,sizeof(ngx_http_myfilter_conf_t));    if(mycf==NULL){        return NULL;    }    //ngx_flat_t 类型的变量。如果使用预设函数ngx_conf_set_flag_slot解析配置项参数,那么必须初始化为NGX_CONF_UNSET    mycf->enable=NGX_CONF_UNSET;    return mycf;}

希望配置不止出现在location{…},还可以出现在server{…}或者http{…}
还需要实现一个配置项值得合并方法-ngx_http_myfilter_merge_conf

static char * ngx_http_myfilter_merge_conf(ngx_conf_t *cf,void *parent,void *child){    ngx_http_myfilter_conf_t *prev=(ngx_http_myfilter_conf_t*)parent;    ngx_http_myfilter_conf_t *conf=(ngx_http_myfilter_conf_t*)child;    //合并ngx_flat_t类型的配置项enable    ngx_conf_merge_value(conf->enable,prev->enable,0);    return NGX_CONF_OK;}

再建立一个http上下文结构体ngx_http_myfilter_ctx_t,其中包括add_prefix整型成员,表示是否添加前缀

typedef struct{    ngx_int_t add_prefix;}ngx_http_myfilter_ctx_t;

为0,表示不加;为1,表示加;为2,表示头已加过

HTTP头部处理方法在1个请求中只会被调用1次。但包体处理方法在1个请求中有可能被多次调用。

定义http过滤模块

定义模块前,需要先定义两个关键成员:ngx_command_t类型的commands数组和ngx_http_module_t类型的ctx 成员
定义ngx_http_myfilter_commands数组,处理配置项,将配置项解析到ngx_http_myfilter_conf_t上下文结构体的成员中
这里写图片描述
在定义ngx_http_module_t类型的ngx_http_myfilter_module_ctx时,需要将ngx_http_myfilter_create_conf回调方法放到create_loc_conf成员;中,ngx_http_myfilter_merge_conf回调方法则要放到merge_loc_conf成员中;
ngx_http_myfilter_init模块初始化方法放到postconfiguration。
这里写图片描述
这里写图片描述

有了ngx_command_t类型的commands数组和ngx_http_module_t类型的ctx之后,就可以定义ngx_http_myfilter_module过滤模块了
这里写图片描述

初始化http过滤模块

在定义ngx_http_myfilter_init方法时,首先需要定义静态指针ngx_http_next_header_filter,用于指向下一个过滤模块的http头部处理方法,定义静态指针ngx_http_next_body_filter,用于指向下一个过滤模块的http包体处理方法
这里写图片描述

处理请求中的http头部

这里写图片描述
这里写图片描述

处理请求的http包体

这里写图片描述
这里写图片描述

0 0
原创粉丝点击