前面我们看到,在HTTP 0.9中处理完请求行后; 在HTTP>=1.0中处理完请求头后,Nginx会调用ngx_http_handler函数对请求进行处理。
/* http/ngx_http_core_module.c */
/* HTTP的phase事件处理函数
* param ev: 待处理的事件
*/
static void ngx_http_phase_event_handler(ngx_event_t *ev)
{
ngx_connection_t *c;
ngx_http_request_t *r;
// 事件ev的custom data为其所属的连接c
c = ev->data;
// 连接c的custom data为其对应的HTTP请求r
r = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "phase event handler");
// 调用ngx_http_run_phases对请求r进行处理
ngx_http_run_phases(r);
return;
}
/* 处理HTTP请求
* param r: 待处理的HTTP请求
*/
void ngx_http_handler(ngx_http_request_t *r)
{
ngx_http_log_ctx_t *lcx;
r->connection->unexpected_eof = 0;
lcx = r->connection->log->data;
lcx->action = NULL;
// 对请求头中的连接类型进行判断
switch (r->headers_in.connection_type) {
case 0:
// 如果为0, 也即是初始值, 表明客户端在请求头中没有提供Connection字段
if (r->http_version > NGX_HTTP_VERSION_10) {
// 如果HTTP版本大于1.0,
// 置r->keepalive为1, 可见在HTTP 1.1中长连接是默认开启的
r->keepalive = 1;
} else {
// HTTP版本不大于1.0时, 长连接默认关闭
r->keepalive = 0;
}
break;
case NGX_HTTP_CONNECTION_CLOSE:
// 连接类型为NGX_HTTP_CONNECTION_CLOSE, 也即客户端在请求头中Connection字段值为close;
// 也即不开启长连接, 连接会在请求处理完毕后断开
r->keepalive = 0;
break;
case NGX_HTTP_CONNECTION_KEEP_ALIVE:
// 连接类型为NGX_HTTP_CONNECTION_KEEP_ALIVE, 也即客户端在请求头中Connection字段值为keep-alive;
// 也即开启长连接
r->keepalive = 1;
break;
}
if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
// 如果开启长连接且客户端的浏览器为MSIE且请求方法为POST
// 置r->keepalive为0, 即不启用长连接, 具体原因据注释说是:
// 当POST请求的响应是通过keepalive连接发送的, 那么MSIE会等待一段时间!
// 对此我表示难以理解
r->keepalive = 0;
}
#if 0
/* TEST STUB */ r->http_version = NGX_HTTP_VERSION_10;
/* TEST STUB */ r->keepalive = 0;
#endif
if (r->headers_in.content_length_n > 0) {
// 如果客户端在请求头中提供Content-Length字段值大于0
// 置r->lingering_close为1, 也即延迟关闭
r->lingering_close = 1;
} else {
r->lingering_close = 0;
}
#if 0
/* TEST STUB */ r->lingering_close = 1;
#endif
// 为该请求对应连接的写事件注册事件处理函数ngx_http_phase_event_handler;
// 从ngx_http_phase_event_handler的定义可以看出, 它也是调用ngx_http_run_phases来对请求进行处理的
r->connection->write->event_handler = ngx_http_phase_event_handler;
// 调用ngx_http_run_phases对请求进行处理
ngx_http_run_phases(r);
return;
}