/**
* 11个阶段处理HTTP请求
*/
void
ngx_http_core_run_phases(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_http_phase_handler_t *ph;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
ph = cmcf->phase_engine.handlers;
/* 遍历解析和处理各个阶段的HTTP请求 如果返回rc==NGX_AGAIN 则交由下一个阶段处理;返回OK则返回结果
* 可以看出ngx_http_request_t结构体中的phase_handler成员将决定执行到哪一个阶段,以及下一个阶段应当执行哪个http模块实现的内容。
*/
while (ph[r->phase_handler].checker) {
rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
if (rc == NGX_OK) {
return;
}
}
}
解析:
rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler])
r->phase_handler作为 cmcf->phase_engine.handlers 数组的index 索引,在checker调用过程中,跳转下一阶段记录在r->phase_handler中,在整个while循环中,通过r->phase_handler在 cmcf->phase_engine.handlers 数组中不断跳转,返回状态rc来决定是否退出while循环。
ngx_http_core_generic_phase()是
NGX_HTTP_POST_READ_PHASE 0
NGX_HTTP_PREACCESS_PHASE 5
NGX_HTTP_TRY_FILES_PHASE 8
这三个阶段的checker,在checker中调用rc = ph->handler®,并根据rc决定r->phase_handler的值,即下一步要执行的阶段cmcf->phase_engine.handlers 数组的位置
/**
* 内容接收阶段
* 有3个http阶段都使用了ngx_http_core_generic_phase作为它们的checker方法,这意味着任何试图在NGX_HTTP_POST_READ_PHASE,NGX_HTTP_PREACCESS_PHASE,
* NGX_HTTP_LOG_PHASE这3个阶段处理请求的http模块都需要了解ngx_http_core_generic_phase到底做了些什么。
*/
ngx_int_t
ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
ngx_int_t rc;
/*
* generic phase checker,
* used by the post read and pre-access phases
*/
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"generic phase: %ui", r->phase_handler);
/*调用这一阶段中各http模块添加的handler处理方法*/
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;
}
/* rc == NGX_ERROR || rc == NGX_HTTP_... */
//如果handler方法返回NGX_ERROR或者类似于NGX_HTTP_ 开头的返回码,则调用ngx_http_finalize_request结束请求
ngx_http_finalize_request(r, rc);
return NGX_OK;
}