10.6.2 NGX_HTTP_POST_READ_PHASE阶段
当HTTP框架在建立的TCP连接上接收到客户发送的完整HTTP请求头部时,开始执行NGX_HTTP_POST_READ_PHASE阶段的checker方法。下面先来看看它的checker方法ngx_http_core_generic_phase,这是一个很典型的checker方法,下面就给出相关代码,以便读者对checker方法的执行过程有个直观认识。
ngx_int_t ngx_http_core_generic_phase(ngx_http_request_tr,ngx_http_phase_handler_tph)
{
//调用这一阶段中各HTTP模块添加的handler处理方法
ngx_int_t rc=ph->handler(r);
/如果handler方法返回NGX_OK,之后将进入下一个阶段处理,而不会理会当前阶段中是否还有其他的处理方法/
if(rc==NGX_OK){
r->phase_handler=ph->next;
return NGX_AGAIN;
}
/如果handler方法返回NGX_DECLINED,那么将进入下一个处理方法,这个处理方法既可能属于当前阶段,也可能属于下一个阶段。注意返回NGX_OK与NGX_DECLINED之间的区别/
if(rc==NGX_DECLINED){
r->phase_handler++;
return NGX_AGAIN;
}
/如果handler方法返回NGX_AGAIN或者NGX_DONE,那么当前请求将仍然停留在这一个处理阶段中/
if(rc==NGX_AGAIN||rc==NGX_DONE){
return NGX_OK;
}
/如果handler方法返回NGXERROR或者类似NGX_HTTP开头的返回码,则调用ngx_http_finalize_request结束请求/
ngx_http_finalize_request(r,rc);
return NGX_OK;
}
任意HTTP模块需要在NGX_HTTP_POST_READ_PHASE阶段处理HTTP请求时,必须首先在ngx_http_core_main_conf_t结构体中的phases[NGX_HTTP_POST_READ_PHASE]动态数组中添加自己实现的ngx_http_handler_pt方法。在此阶段中,ngx_http_handler_pt方法的返回值可以产生4种不同的影响,总结见表10-1。
目前,官方的ngx_http_realip_module模块是从NGX_HTTP_POST_READ_PHASE阶段介入以处理HTTP请求的,它在postconfiguration方法中是这样将自定义的ngx_http_handler_pt处理方法添加到HTTP框架中的,如下所示。
//这个ngx_http_realip_init方法实际上就是postconfiguration接口的实现
static ngx_int_t ngx_http_realip_init(ngx_conf_t*cf)
{
ngx_http_handler_pt*h;
//首先获取到全局的ngx_http_core_main_conf_t结构体
ngxhttp_core_main_conf_t*cmcf=ngx_http_conf_get_module_main_conf(cf,ngx
http_core_module);
/phases数组中有11个成员,取出NGX_HTTP_POST_READ_PHASE阶段的handlers动态数组,向其中添加ngx_http_handler_pt处理方法,这样ngx_http_realip_module模块就介入HTTP请求的NGX_HTTP_POST_READ_PHASE处理阶段了/
h=ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
if(h==NULL){
return NGX_ERROR;
}
/ngx_http_realip_handler方法就是实现了ngx_http_handler_pt接口的方法/
*h=ngx_http_realip_handler;
/实际上,同一个HTTP模块的同一个ngx_http_realip_handler方法,完全可以设置到两个不同的阶段中的。例如,phases[NGX_HTTP_PREACCESS_PHASE.handlers]动态数组中也添加了ngx_http_realip_handler方法/
h=ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
if(h==NULL){
return NGX_ERROR;
}
/ngx_http_realip_handler处理方法同时介入了NGX_HTTP_POST_READ_PHASE、NGX_HTTP_PREACCESS_PHASE这两个HTTP处理阶段/
*h=ngx_http_realip_handler;
return NGX_OK;
}
通过这个例子可以看到怎样在NGX_HTTP_POST_READ_PHASE或者NGX_HTTP_PREACCESS_PHASE阶段添加HTTP模块。