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节中介绍的一些必需的过滤模块具备的功能来决定。