6.4.5 处理请求中的HTTP头部
我们需要把在HTTP响应包体前加的字符串前缀硬编码为filter_prefix变量,如下所示。
static ngx_str_t filter_prefix=ngx_string("[my filter prefix]");
根据图6-2中描述的处理流程,ngx_http_myfilter_header_filter回调方法的实现应如下所示。
static ngx_int_t
ngx_http_myfilter_header_filter(ngx_http_request_t*r)
{
ngx_http_myfilter_ctx_t*ctx;
ngx_http_myfilter_conf_t*conf;
/如果不是返回成功,那么这时是不需要理会是否加前缀的,直接交由下一个过滤模块处理响应码非200的情况/
if(r->headers_out.status!=NGX_HTTP_OK){
return ngx_http_next_header_filter(r);
}
//获取HTTP上下文
ctx=ngx_http_get_module_ctx(r,ngx_http_myfilter_module);
if(ctx){
/该请求的上下文已经存在,这说明ngx_http_myfilter_header_filter已经被调用过1次,直接交由下一个过滤模块处理/
return ngx_http_next_header_filter(r);
}
//获取存储配置项的ngx_http_myfilter_conf_t结构体
conf=ngx_http_get_module_loc_conf(r,ngx_http_myfilter_module);
/如果enable成员为0,也就是配置文件中没有配置add_prefix配置项,或者add_prefix配置项的参数值是off,那么这时直接交由下一个过滤模块处理/
if(conf->enable==0){
return ngx_http_next_header_filter(r);
}
//构造HTTP上下文结构体ngx_http_myfilter_ctx_t
ctx=ngx_pcalloc(r->pool,sizeof(ngx_http_myfilter_ctx_t));
if(ctx==NULL){
return NGX_ERROR;
}
//add_prefix为0表示不加前缀
ctx->add_prefix=0;
//将构造的上下文设置到当前请求中
ngx_http_set_ctx(r,ctx,ngx_http_myfilter_module);
//myfilter过滤模块只处理Content-Type是“text/plain”类型的HTTP响应
if(r->headers_out.content_type.len>=sizeof("text/plain")-1
&&ngx_strncasecmp(r->headers_out.content_type.data,(u_char*)"text/plain",sizeof("text/plain")-1)==0)
{
//设置为1表示需要在HTTP包体前加入前缀
ctx->add_prefix=1;
/当处理模块已经在Content-Length中写入了HTTP包体的长度时,由于我们加入了前缀字符串,所以需要把这个字符串的长度也加入到Content-Length中/
if(r->headers_out.content_length_n>0)
r->headers_out.content_length_n+=filter_prefix.len;
}
//交由下一个过滤模块继续处理
return ngx_http_next_header_filter(r);
}
注意,除非出现了严重的错误,一般情况下都需要交由下一个过滤模块继续处理。究竟是在ngx_http_myfilter_header_filter函数中直接返回NGX_ERROR,还是调用ngx_http_next_header_filter(r)继续处理,读者可以参考6.2.3节中介绍的一些必需的过滤模块具备的功能来决定。