异想天开

What's the true meaning of light, Could you tell me why

nginx的http request处理-nginx源码阅读6

日期:2014-06-06 16:04:24
  
最后更新日期:2014-11-25 14:24:16
总结:
主要说明http request怎么实现依次调用每一阶段的hanlder的部分。

nginx的http解析以及处理request,可以看成为一个状态机,某一状态处理完即进入下一状态。nginx处理一个http request分为11个阶段。由一个枚举变量定义。
[code lang="cpp"]
typedef enum {
//读取请求
NGX_HTTP_POST_READ_PHASE = 0,
//处理全局的(server block)的rewrite阶段
NGX_HTTP_SERVER_REWRITE_PHASE,

//通过uri来查找对应的location,关联uri和location的数据的阶段
NGX_HTTP_FIND_CONFIG_PHASE,
//处理location的rewrite阶段
NGX_HTTP_REWRITE_PHASE,
//post rewrite,进行一些校验以及收尾工作,以便于交给后面的模块
NGX_HTTP_POST_REWRITE_PHASE,
//粗粒度的access校验
NGX_HTTP_PREACCESS_PHASE,
//细粒度的access校验
NGX_HTTP_ACCESS_PHASE,
//判断前面校验返回值的阶段
NGX_HTTP_POST_ACCESS_PHASE,
//try_file模块
NGX_HTTP_TRY_FILES_PHASE,
//内容处理模块
NGX_HTTP_CONTENT_PHASE,
//log模块
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
[/code]
gdb跟踪(gdb -p 进程号)在ngx_http_init_connection设置断点,在一个连接过来后,跟踪读事件的hanler,可以得到如下调用序列: [code lang="cpp"]
ngx_http_init_connection -> ngx_http_wait_request_handler -> ngx_http_process_request_line -> ngx_http_process_request_headers
-> ngx_http_process_request -> ngx_http_handler -> ngx_http_core_run_phases
[/code]

最后为ngx_http_core_run_phases,依次对每个阶段(phases)一个或多个handler进行处理。
[code lang="cpp"]
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;

while (ph[r->phase_handler].checker) {

rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);

if (rc == NGX_OK) {
return;
}
}
}
[/code]

该函数读取http main的配置项phase_engine,http main的回调函数ngx_http_block有个步骤ngx_http_init_phase_handlers包含初始化phase_engine过程。ngx_http_core_main_conf_t定义如下:
[code lang="cpp"]
typedef struct {
ngx_array_t servers; /* ngx_http_core_srv_conf_t */

ngx_http_phase_engine_t phase_engine;
...
ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1];
} ngx_http_core_main_conf_t;
[/code]
上诉结构体phases成员类型ngx_http_phase_t,实为一个数组即每一阶段可能不止一个handler,故为数组的数组形式:
[code lang="cpp"]
typedef struct {
ngx_array_t handlers;
} ngx_http_phase_t;
[/code]
而phase_engineze的类型ngx_http_phase_engine_t,handlers则为一个动态数组,定义如下:
[code lang="cpp"]
typedef struct {
ngx_http_phase_handler_t *handlers;
ngx_uint_t server_rewrite_index;
ngx_uint_t location_rewrite_index;
} ngx_http_phase_engine_t;
[/code]
使用动态数组后,可以将phases这种数组的数组的形式全部放进一个动态数组phase_engine->handlers里面。

可以看出handler结构为了适应这种动态数组成定义如下:
[code lang="cpp"]
struct ngx_http_phase_handler_s {
ngx_http_phase_handler_pt checker;
ngx_http_handler_pt handler;
ngx_uint_t next;
};
[/code]
ngx_http_phase_handler_t为ngx_http_phase_handler_s的typedef。
注:
1.checker在ngx_http_core_run_phases用来判断循环是否结束。
2.在checker会调用handler,会修改r->phase_handler的值,相当于把iteror++。
3.next为数组的索引,指向下一个阶段的起始位置,同一个阶段有多个handler时,next时一般相等。checher函数可以根据handler的返回值来判断是否进行同一阶段的下一handler,还是进入下一个阶段。比如注册了多个防盗链模块,这些防盗链模块都是在NGX_HTTP_ACCESS_PHASE阶段的不同handler,假如第一个防盗链模块返回为403
那么就没有必要进行下一个防盗链校验了。