32.Nginx HTTP之ngx_http_handler函数

詹弘毅
2023-12-01

前面我们看到,在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;
}


 类似资料: