nginx request
在nginx系列nginx2中 我们理解了nginx针对连接的处理,下面我们来看看nginx针对http怎么进一步处理,nginx基于connect构建request request封装的是对http的请求,即http,请求头,请求体,响应头,响应体,从ngx_http_init_connection函数开始,设置读,写处理函数 在ngx_http_wait_request_handler读函数中最终设置读为ngx_http_process_request_line且调用,也就是说接下来的网络事件都由 该函数来处理
//src/http/ngx_http_request.c void ngx_http_init_connection(ngx_connection_t *c)
rev = c->read;
rev->handler = ngx_http_wait_request_handler;
c->write->handler = ngx_http_empty_handler;
...
rev->handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);
nginx ngx_http_process_request_line
首先通过调用ngx_http_read_request_header来获取请求请求数据,然后调用ngx_http_parse_request_line来获取请求数据
通过ngx_http_read_request_header获取请求头,以及一些校验,并将参数保存到ngx_http_request_t。解析完请求后会把读事件
设置成ngx_http_process_request_headers,后续的请求就会在该函数读取与解析,该函数也是调用ngx_http_read_request_header来读取请求头
并调用ngx_http_parse_header_line获取一行请求头数据,解析到的请求头会保存到 ngx_http_request_t 的域 headers_in中
headers_in 是一个链表结构,保存所有的请求头,有些请求头是需要特别处理,nginx会把请求头与处理函数存放在ngx_http_headers_in里,
初始化的时候,会生成一个hash表当每解析到一个请求头后,就会先在这个 hash 表中查找,如果 有找到,则调用相应的处理函数来处理这个请求头。比如:Host 头的处理函数是ngx_http_process_host。
当nginx解析到结束标\r\n的时候 代表请求头读完了,会调用ngx_http_process_request来处理请求体。具体代码如下
//这里设置的读写都是ngx_http_request_handler,在该函数中,会根据当前事件是读还是写事件调用read_event_handler/write_event_handler
c->read->handler = ngx_http_request_handler;
c->write->handler = ngx_http_request_handler;
//不读取数据了 由handler去读取
r->read_event_handler = ngx_http_block_reading;
//真正开始处理数据
ngx_http_handler(r);
这个函数会设置写事件为ngx_http_core_run_phases,并执行ngx_http_core_run_phases
r->write_event_handler = ngx_http_core_run_phases;
接下来我们来看核心,这个函数将执行多阶段请求处理nginx 将一个 http请求的处理分为多个阶段,那么这个函数就是执行这些阶段来产生数据。对于将写事件 设置成ngx_http_core_run_phases,我们看下函数调用逻辑,最终是调用ngx_http_core_run_phases来处理请求,产生的响应头会放在ngx_http_request_t的headers_out中 而且各阶段会对请求进行处理,最后调用filter来过滤数据,对数据进行加工,如文件的trucked传输,gzip压缩
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;
}
}
}
//http状态及11阶段
typedef enum {
//注册handler函数到该阶段 //对应状态模块
NGX_HTTP_POST_READ_PHASE = 0, //realip
//重写server配置的url
NGX_HTTP_SERVER_REWRITE_PHASE, //rewrite
//查找location 配置
NGX_HTTP_FIND_CONFIG_PHASE,
//location 重写url
NGX_HTTP_REWRITE_PHASE, //rewrite
//检查是否发生了url重写,是则回到NGX_HTTP_FIND_CONFIG_PHASE
NGX_HTTP_POST_REWRITE_PHASE,
//访问控制阶段
NGX_HTTP_PREACCESS_PHASE, //limit_conn,limit_req
//访问权限控制
NGX_HTTP_ACCESS_PHASE, //auth_basic,access,auth_request
//处理权限控制
NGX_HTTP_POST_ACCESS_PHASE,
//内容预处理 配置try_files或mirror才会进入
NGX_HTTP_PRECONTENT_PHASE, //try_files
//内容产生阶段,返回给客户端
NGX_HTTP_CONTENT_PHASE, //index,autoindex,concat
//记录日志阶段
NGX_HTTP_LOG_PHASE //access_log
} ngx_http_phases;
nginx http filter
filter 是一个链表结构,分别有header filter与body filter,先执行header filter 中的所有filter,然后再执行 body filter中的所有filter。
在header filter中的最后一个filter,即ngx_http_header_filter, 这个filter将会遍历所有的响应头,最后需要输出的响应头在一个连续的内存,然后调用
ngx_http_write_filter进行输出。ngx_http_write_filter是body filter中的最 后一个,所以nginx首先的body信息,在经过一系列的body filter之后,
最后也会调 用ngx_http_write_filter来进行输出
最后所有的请求头会放入buffer里,大小在nginx.conf里配置client_header_buffer_size
objs/ngx_module.c ngx_module_names数组里
"ngx_http_write_filter_module",
"ngx_http_header_filter_module",
"ngx_http_chunked_filter_module",
"ngx_http_range_header_filter_module",
"ngx_http_gzip_filter_module",
"ngx_http_postpone_filter_module",
"ngx_http_ssi_filter_module",
"ngx_http_charset_filter_module",
"ngx_http_addition_filter_module",
"ngx_http_userid_filter_module",
"ngx_http_headers_filter_module",
"ngx_http_copy_filter_module",
"ngx_http_range_body_filter_module",
"ngx_http_not_modified_filter_module",
//todo 剩余一张完整流程的图