nginx过滤post请求头_Nginx:HTTP过滤模块

本文介绍了如何创建一个Nginx HTTP过滤模块,该模块在静态文件响应中添加一个自定义前缀。通过配置项`add_prefix`控制过滤模块是否生效,确保在HTTP响应包头添加一次前缀。过滤模块主要包含配置解析、HTTP上下文处理、头部及包体过滤等部分的实现。
摘要由CSDN通过智能技术生成

参考资料

HTTP过滤模块也是一种HTTP模块,与普通HTTP处理模块不同在于:

1.一个请求仅由一个HTTP处理模块处理,而可以被任意个HTTP过滤模块处理

2.普通的HTTP模块倾向于完成请求的核心功能,而HTTP过滤模块所做的工作是对发送给用户的HTTP响应包做一些加工

HTTP过滤模块的简单例子

该过滤模块实现的功能是:用户的请求由static静态文件模块进行处理,根据URI返回磁盘中的文件给用户,然后该过滤模块就会在返回给用户的相应包体前添加一段字符串:"[my filter prefix]"

static静态文件模块处理完成后会调用ngx_http_send_header跟ngx_http_output_filter来调用过滤模块

1.编写config文件

跟普通HTTP模块不同的是HTTP_MODULES变量要改为HTTP_FILTER_MODULES

ngx_addon_name=ngx_http_myfilter_module

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

2.配置项与上下文

该过滤模块希望在nginx.conf中由一个控制当前HTTP过滤模块是否生效的配置项,它的参数值是on或者off。首先建立如下结构来存储配置项

typedef struct{

ngx_flag_t enable;

} ngx_http_myfilter_conf_t;

下面实现的ngx_http_myfilter_create_conf用于为存储配置项的结构体分配内存

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){returnNULL;

}

mycf->enable=NGX_CONF_UNSET;returnmycf;

}

因为Nginx的异步处理,一个HTTP包体处理方法在1个请求中可能被多次调用,而实际上我们只希望在包头加1次前缀。因此再建立一个HTTP上下文结构体来处理HTTP包体时是否添加前缀

typedef struct{

ngx_int_t add_prefix;

} ngx_http_myfilter_ctx_t;

3.定义HTTP过滤模块,与普通的HTTP模块类似,不多解释。

定义ngx_http_myfilter_commands数组,出现配置项是使用Nginx预设的方法ngx_conf_set_flag_slot来处理

static ngx_command_t ngx_http_myfilter_commands[]={

{//配置项名称

ngx_string("add_prefix"),//配置项类型(可出现的位置,参数的个数)

NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_FLAG,//出现了name中指定的配置项后,将会调用该方法处理配置项的参数

ngx_conf_set_flag_slot,

NGX_HTTP_LOC_CONF_OFFSET,

offsetof(ngx_http_myfilter_conf_t,enable),

NULL

},

ngx_null_command

};

定义ngx_http_module_t,ngx_http_myfilter_init方法用于初始化HTTP过滤模块,下面有它的实现代码

static ngx_http_module_t ngx_http_myfilter_module_ctx={

NULL,

ngx_http_myfilter_init,

NULL,

NULL,

NULL,

NULL,

ngx_http_myfilter_create_conf,

NULL

};

定义ngx_module_t

ngx_module_t ngx_http_myfilter_module={

NGX_MODULE_V1,//指向ngx_http_module_t结构体

&ngx_http_myfilter_module_ctx,//用来处理nginx.conf中的配置项

ngx_http_myfilter_commands,//表示该模块的类型

NGX_HTTP_MODULE,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NGX_MODULE_V1_PADDING

};

4.初始化HTTP过滤模块

一个请求可以由多个过滤模块处理,所以过滤模块是有调用顺序的,该方法用于构建过滤链表

//用于初始化HTTP过滤模块

staticngx_http_output_header_filter_pt ngx_http_next_header_filter;staticngx_http_output_body_filter_pt ngx_http_next_body_filter;static ngx_int_t ngx_http_myfilter_init(ngx_conf_t *cf)

{//插入到头部处理方法链表的首部

ngx_http_next_header_filter=ngx_http_top_header_filter;

ngx_http_top_header_filter=ngx_http_myfilter_header_filter;//插入包体处理方法链表的首部

ngx_http_next_body_filter=ngx_http_top_body_filter;

ngx_http_top_body_filter=ngx_http_myfilter_body_filter;returnNGX_OK;

}

static ngx_str_t filter_prefix = ngx_string("[filter_prefix]");

5.处理请求的HTTP头部

1 staticngx_int_t2 ngx_http_myfilter_header_filter(ngx_http_request_t *r)3 {4 ngx_http_myfilter_ctx_t *ctx;5 ngx_http_myfilter_conf_t *conf;6 //如果返回失败,则直接交由下一个过滤模块处理

7 if(r->headers_out.status!=NGX_HTTP_OK){8 returnngx_http_next_header_filter(r);9 }10 //获取HTTP上下文

11 ctx=ngx_http_get_module_ctx(r,ngx_http_myfilter_module);12 if(ctx){13 //如果请求的上下文已经存在,说明ngx_http_myfilter_header_filter已经被调用过1次

14 returnngx_http_next_header_filter(r);15 }16 //获取存储配置项的ngx_http_myfilter_conf结构体

17 conf=ngx_http_get_module_loc_conf(r,ngx_http_myfilter_module);18 //如果enable成员为0,则直接交给下一个

19 if(conf->enable==0){20 returnngx_http_next_header_filter(r);21 }22 //构造上下文结构体ngx_http_myfilter_ctx_t

23 ctx=ngx_pcalloc(r->pool,sizeof(ngx_http_myfilter_ctx_t));24 if(ctx==NULL){25 returnNGX_ERROR;26 }27 //add_prefix为0表示不加前缀

28 ctx->add_prefix=0;29 //将构造的上下文设置到当前请求

30 ngx_http_set_ctx(r,ctx,ngx_http_myfilter_module);31 //myfilter过滤模块只处理Content-Type是"text-plain"类型的HTTP响应

32 if(r->headers_out.content_type.len>=sizeof("text/plain")-1

33 && ngx_strncasecmp(r->headers_out.content_type.data,(u_char *)"text/plain",sizeof("text/plain")-1)==0)34 {35 //设置为1表示需要再HTTP包体前加入前缀

36 ctx->add_prefix=1;37 //把前缀字符串的长度加入Content-length中

38 if(r->headers_out.content_length_n>0){39 r->headers_out.content_length_n+=filter_prefix.len;40 }41 }42 //交由下一个过滤模块继续处理

43 returnngx_http_next_header_filter(r);44 }

View Code

6.处理请求的HTTP包体

1 //处理请求中的HTTP包体

2 staticngx_int_t3 ngx_http_myfilter_body_filter(ngx_http_request_t *r,ngx_chain_t *in)4 {5 ngx_http_myfilter_ctx_t *ctx;6 ctx=ngx_http_get_module_ctx(r,ngx_http_myfilter_module);7 //如果获取不到上下文,或者上下文结构体中add_prefix为0或2时,都不会添加前缀

8 if(ctx==NULL||ctx->add_prefix!=1){9 return ngx_http_next_body_filter(r,in);10 }11 //将add_prefix设置为2,防止重复添加前缀

12 ctx->add_prefix=2;13 //分配内存用于存储字符串前缀

14 ngx_buf_t *b=ngx_create_temp_buf(r->pool,filter_prefix.len);15 //将ngx_buf_t中的指针指向filter_prefix字符串

16 b->start=b->pos=filter_prefix.data;17 b->last=b->pos+filter_prefix.len;18 //生成要发送的ngx_chain_t链表,加上刚分配的ngx_buf_t成员

19 ngx_chain_t *cl=ngx_alloc_chain_link(r->pool);20 cl->buf=b;21 cl->next=in;22 //调用下一个过滤模块

23 returnngx_http_next_body_filter(r,cl);24 }

View Code

7.配置nginx.conf文件

添加如下配置,在nginx安装目录下添加txt/test.txt文件,访问localhost/test.txt。

location /{

root txt;

add_prefix on;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值