Nginx源码分析之--http框架

Nginx的http功能和模块使用广泛,那么Nginx的http框架是如何初始化的呢?http请求的11个处理阶段又是怎么设计的呢?

http框架初始化流程图

结合流程简图和代码描述总体流程

当配置文件nginx.conf配置了http{...}并被解析到时,http框架通过执行ngx_http_block函数开始初始化:

static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    char                        *rv;
    ngx_uint_t                   mi, m, s;
    ngx_conf_t                   pcf;
    ngx_http_module_t           *module;
    ngx_http_conf_ctx_t         *ctx;
    ngx_http_core_loc_conf_t    *clcf;
    ngx_http_core_srv_conf_t   **cscfp;
    ngx_http_core_main_conf_t   *cmcf;

    if (*(ngx_http_conf_ctx_t **) conf) {
        return "is duplicate";
    }

    /* the main http context */

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    *(ngx_http_conf_ctx_t **) conf = ctx;

    /*初始化所有HTTP模块的ctx_index序号*/
    ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);

    /*分配解析http{}块下main级别配置项时存放HTTP模块结构体指针的3个数组main_conf、srv_conf、loc_conf*/
    ctx->main_conf = ngx_pcalloc(cf->pool,
                                 sizeof(void *) * ngx_http_max_module);
    if (ctx->main_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }

    /*
     * 处理http{}块内的main级别配置时,对每个HTTP模块,都会调用create_(main|srv|loc)_conf等3个方法
     */
    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue; //跳过非http模块
        }

        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;

        if (module->create_main_conf) {
            ctx->main_conf[mi] = module->create_main_conf(cf); //main级别
            if (ctx->main_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_srv_conf) {
            ctx->srv_conf[mi] = module->create_srv_conf(cf); //server级别
            if (ctx->srv_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        if (module->create_loc_conf) {
            ctx->loc_conf[mi] = module->create_loc_conf(cf); //location级别
            if (ctx->loc_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
    }

    pcf = *cf;
    cf->ctx = ctx;

    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;

        if (module->preconfiguration) {
            if (module->preconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }

    /* 解析http{} main配置 */
    cf->module_type = NGX_HTTP_MODULE;
    cf->cmd_type = NGX_HTTP_MAIN_CONF;
    rv = ngx_conf_parse(cf, NULL); //解析内部配置

    if (rv != NGX_CONF_OK) {
        goto failed;
    }

    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
    cscfp = cmcf->servers.elts;

    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;

        //调用所有HTTP模块的init_main_conf方法,保存main级别配置
        if (module->init_main_conf) {
            rv = module->init_main_conf(cf, ctx->main_conf[mi]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }

        //合并ngx_modules[m]模块main、srv、loc配置
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
        if (rv != NGX_CONF_OK) {
            goto failed;
        }
    }

    /* 构造location组成的静态二叉平衡查找树 */
    for (s = 0; s < cmcf->servers.nelts; s++) {

        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

        //将ngx_http_core_loc_conf_t组成的双向链表按照location匹配字符串进行排序
        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        //根据已经排序过的的双向链表,构建静态的二叉查找树
        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }

    /* 初始化可添加处理方法的HTTP阶段的动态数组 */
    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    /* 调用所有HTTP模块的postconfiguration方法,使之可以介入HTTP请求处理阶段 */
    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;

        if (module->postconfiguration) {
            if (module->postconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }

    if (ngx_http_variables_init_vars(cf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    /*
     * http{}'s cf->ctx was needed while the configuration merging
     * and in postconfiguration process
     */

    *cf = pcf;

    //根据各个HTTP模块介入的处理方法构造出phase_engine_handlers数组
    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    //构造监听端口与server间的关联关系,设置新连接事件的回调方法
    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;

failed:

    *cf = pcf;

    return rv;
}

初始化所有HTTP模块的ctx_index序号

  • ctx_index表示模块在同类型模块中的索引,比如ngx_http_core_module是HTTP模块(NGX_HTTP_MODULE)的首个模块,那么该模块的ctx_index为0。

分配解析http{}块下main级别配置项时存放HTTP模块结构体指针的3个数组

  • 分配main_conf数组用于保存各个HTTP模块在main级别可能创建的xx_main_conf_t结构体
  • 分配srv_conf数组用于保存各个HTTP模块在main级别可能创建的xx_srv_conf_t结构体
  • 分配loc_conf数组用于保存各个HTTP模块在main级别可能创建的xx_loc_conf_t结构体
  • 另外,必须同时创建3个数组。因为对于HTTP模块来说,某个指令有可能同时出现在main、srv、loc级别。实际应用配置项时,具体以那个级别的配置项为准,需要合并处理。

依次调用所有HTTP模块的create_(main|srv|loc)_conf共3个方法

每个HTTP模块可以实现模块上下文ngx_http_module_t的这3个回调方法,如果实现,则:

  • 调用create_main_conf,分配每个HTTP模块main级别的xx_main_conf_t结构体内存,并对字段赋初始值
  • 调用create_srv_conf,分配每个HTTP模块main级别的xx_srv_conf_t结构体内存,并对字段赋初始值
  • 调用create_loc_conf,分配每个HTTP模块main级别的xx_loc_conf_t结构体内存,并对字段赋初始值

调用所有HTTP模块的preconfiguration方法

每个HTTP模块可以实现模块上下文ngx_http_module_tpreconfiguration回调方法,如果实现,则:

  • 调用preconfiguration方法, 一般用于添加变量

解析http{}块下的所有main级别配置项

  • 交由conf模块解析http{}块下的配置
    • 特别的,如果内部碰到server{}块时,则会分配srv_conf、loc_conf数组分别用于保存各个HTTP模块在server级别可能创建的xx_srv_conf_t、xx_loc_conf_t结构体。然后调用create_srv_conf、create_loc_conf分配每个HTTP模块在server级别的xx_(srv|loc)_conf_t结构体内存,并对字段赋初始值
      • 特别的,如果内部碰到location{}块时,则会分配loc_conf数组分别用于保存各个HTTP模块在location级别可能创建的xx_loc_conf_t结构体。然后调用create_loc_conf分配每个HTTP模块在location级别的xx_loc_conf_t结构体内存,并对字段赋初始值
      • location{}下的配置解析完,则各个HTTP模块在location级别的xxx_loc_conf_t结构体赋值完成
    • server{}下的配置解析完,则各个HTTP模块在server级别的xx_(srv|loc)_conf_t结构体赋值完成

调用所有HTTP模块的init_main_conf方法

每个HTTP模块可以实现模块上下文ngx_http_module_t的init_main_conf回调方法, 如果实现,则:

  • 配置解析完成后,调用init_main_conf方法,最终确定并保存各个HTTP模块在main级别的xx_main_conf_t配置结构体

合并main、srv、loc级别下server、location相关的配置项

对每一server{}而言,每个HTTP模块可以实现模块上下文ngx_http_module_t的merge_srv_conf和merge_loc_conf回调方法, 如果实现,则:

  • 调用merge_srv_conf和merge_loc_conf方法,最终确定并保存各个HTTP模块在server级别的xx_(srv|loc)_conf_t配置结构体

对于每一个location{}而言,每个HTTP模块可以实现模块上下文ngx_http_module_t的merge_loc_conf回调方法, 如果实现, 则:

  • 调用merge_loc_conf方法,最终确定并保存各个HTTP模块在location级别的xx_loc_conf_t配置结构体

构造location组成的静态二叉平衡查找树

对于每一个server而言,

  • 将ngx_http_core_loc_conf_t组成的双向链表按照location匹配字符串进行排序
  • 根据已经排序过的的双向链表,构建静态的二叉查找树。这样处理请求时可以加速找到location

初始化可添加处理方法的HTTP阶段的动态数组

  • http请求处理的11个阶段,分配数组,用于后续添加模块自定义的handler方法

调用所有HTTP模块的postconfiguration方法使之可以介入HTTP阶段

每个HTTP模块可以实现模块上下文ngx_http_module_tpostconfiguration方法,如果实现,则:

  • 调用postconfiguration,将handler方法添加到上一步常见的某个阶段(哪个阶段由模块自行决定,但只有7个阶段可以介入)的数组中

根据各个HTTP模块介入的处理方法构造出phase_engine_handlers数组

  • 根据前两步构造的的动态数组,调用ngx_http_init_phase_handlers函数构造出phase_engine_handlers数组
  • 特别的,有四个阶段不允许介入或者介入无效,分别是:NGX_HTTP_FIND_CONFIG_PHASE
    NGX_HTTP_POST_REWRITE_PHASENGX_HTTP_POST_ACCESS_PHASE
    NGX_HTTP_PRECONTENT_PHASE(旧的Nginx的try_files阶段)
  • 特别的,NGX_HTTP_CONTENT_PHASE阶段,除了常规的postconfiguration介入方式(这种方式影响所有的location)。另外可以直接以ngx_command_t指定location的handler方式介入,只对location有该指令的location生效
  • 特别的, 记录http日志(最后一个阶段log)特殊处理,并不会出现在phase_engine_handlers数组中

构造server虚拟主机构成的支持通配符的散列表

  • ngx_http_server_names将server虚拟主机和对应的ngx_http_core_srv_conf_t结构体指针哈希化关联起来,这样处理请求时可以快速匹配server

构造监听端口与server间的关联关系,并设置新连接事件的回调方法

  • 将监听端口ngx_http_conf_port_t和addr地址ngx_http_conf_addr_t关联
  • 进一步,将ngx_http_conf_addr_t和server虚拟主机关联。该结构体有3个哈希表结构字段,
    分别用于索引完全匹配的sever_name、通配符前置、通配符后置的server虚拟主机结构体ngx_http_core_srv_conf_t结构体指针
  • 设置新连接事件的回调方法: ngx_http_init_connection

http请求的11个阶段

构造phase_engine_handlers数组

  • ngx_http_init_phase_handlers函数在http初始化时调用
//根据各个HTTP模块介入的处理方法构造出phase_engine_handlers数组
static ngx_int_t
ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
{
    ngx_int_t                   j;
    ngx_uint_t                  i, n;
    ngx_uint_t                  find_config_index, use_rewrite, use_access;
    ngx_http_handler_pt        *h;
    ngx_http_phase_handler_t   *ph;
    ngx_http_phase_handler_pt   checker;

    cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
    cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
    find_config_index = 0;
    use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
    use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;

    n = 1                  /* find config phase */
        + use_rewrite      /* post rewrite phase */
        + use_access;      /* post access phase */

    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { //注意:不包含NGX_HTTP_LOG_PHASE阶段,该阶段另行特殊处理
        n += cmcf->phases[i].handlers.nelts; //累加计算总的HTTP阶段处理方法个数
    }

    ph = ngx_pcalloc(cf->pool,
                     n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
    if (ph == NULL) {
        return NGX_ERROR;
    }

    cmcf->phase_engine.handlers = ph;
    n = 0;

    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { //注意: 不包含NGX_HTTP_LOG_PHASE阶段
        h = cmcf->phases[i].handlers.elts;

        switch (i) {

        case NGX_HTTP_SERVER_REWRITE_PHASE:
            if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
                cmcf->phase_engine.server_rewrite_index = n;
            }
            checker = ngx_http_core_rewrite_phase;

            break;

        case NGX_HTTP_FIND_CONFIG_PHASE:
            find_config_index = n;

            ph->checker = ngx_http_core_find_config_phase;
            n++;
            ph++;

            continue;

        case NGX_HTTP_REWRITE_PHASE:
            if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
                cmcf->phase_engine.location_rewrite_index = n;
            }
            checker = ngx_http_core_rewrite_phase;

            break;

        case NGX_HTTP_POST_REWRITE_PHASE:
            if (use_rewrite) {
                ph->checker = ngx_http_core_post_rewrite_phase;
                ph->next = find_config_index;
                n++;
                ph++;
            }

            continue;

        case NGX_HTTP_ACCESS_PHASE:
            checker = ngx_http_core_access_phase;
            n++;
            break;

        case NGX_HTTP_POST_ACCESS_PHASE:
            if (use_access) {
                ph->checker = ngx_http_core_post_access_phase;
                ph->next = n;
                ph++;
            }

            continue;

        case NGX_HTTP_CONTENT_PHASE:
            checker = ngx_http_core_content_phase;
            break;

        default: //NGX_HTTP_POST_READ_PHASE、NGX_HTTP_PREACCESS_PHASE、NGX_HTTP_PRECONTENT_PHASE
            checker = ngx_http_core_generic_phase;
        }

        n += cmcf->phases[i].handlers.nelts; //跳过本阶段的所有handler, 也即下一阶段的首个handler

        //注意:每个HTTP处理阶段中最后加入到handlers[]中的会首先添加到cmcf->phase_engine.handlers
        for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
            ph->checker = checker;
            ph->handler = h[j];
            ph->next = n; //下一阶段的首个handler序号
            ph++;
        }
    }

    return NGX_OK;
}

checker方法

ngx_http_core_generic_phase

/*
 * NGX_HTTP_(POST_READ | PREACCESS | PRECONTENT)_PHASE等阶段的checker方法
 */
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处理方法(由各个HTTP模块的postconfiguration钩子函数添加)
    rc = ph->handler(r);

    if (rc == NGX_OK) {
        r->phase_handler = ph->next; //rc为NGX_OK时,进入下一阶段就行处理, 当前阶段即使有其他处理方法也会跳过
        return NGX_AGAIN;
    }

    if (rc == NGX_DECLINED) {
        r->phase_handler++; //下一个处理方法,可能仍是当前阶段,也有可能是下一个阶段的首个处理方法
        return NGX_AGAIN;
    }

    if (rc == NGX_AGAIN || rc == NGX_DONE) {
        return NGX_OK; //不更改r->phase_handler的值,当前处理方法有机会再次被调用。但是必须把控制权交还event模块
    }

    /* rc == NGX_ERROR || rc == NGX_HTTP_...  */

    ngx_http_finalize_request(r, rc); //返回错误NGX_ERROR或者NGX_HTTP_开头的返回码,则结束请求

    return NGX_OK;
}

ngx_http_core_rewrite_phase

/*
 * NGX_HTTP_(SERVER_REWRITE | REWRITE)_PHASE等阶段的checker方法
 */
ngx_int_t
ngx_http_core_rewrite_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
    ngx_int_t  rc;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "rewrite phase: %ui", r->phase_handler);

    rc = ph->handler(r); //执行挂载的handler方法

    if (rc == NGX_DECLINED) {
        r->phase_handler++; //当前处理方法执行完毕,执行下一个处理方法
        return NGX_AGAIN;
    }

    if (rc == NGX_DONE) {
        return NGX_OK; //不更改r->phase_handler的值,当前处理方法有机会再次被调用。但是必须把控制权交还event模块
    }

    /* NGX_OK, NGX_AGAIN, NGX_ERROR, NGX_HTTP_...  */

    ngx_http_finalize_request(r, rc); //结束请求

    return NGX_OK;
}

ngx_http_core_find_config_phase

/*
 * 根据请求的URI寻找匹配的location表达式,不允许用户模块介入。即使介入也无效,因为入参ph未使用
 */
ngx_int_t
ngx_http_core_find_config_phase(ngx_http_request_t *r,
    ngx_http_phase_handler_t *ph)
{
    u_char                    *p;
    size_t                     len;
    ngx_int_t                  rc;
    ngx_http_core_loc_conf_t  *clcf;

    r->content_handler = NULL;
    r->uri_changed = 0;

    rc = ngx_http_core_find_location(r);

    if (rc == NGX_ERROR) {
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_OK;
    }

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (!r->internal && clcf->internal) {
        ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
        return NGX_OK;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "using configuration \"%s%V\"",
                   (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")),
                   &clcf->name);

    ngx_http_update_location_config(r);

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http cl:%O max:%O",
                   r->headers_in.content_length_n, clcf->client_max_body_size);

    if (r->headers_in.content_length_n != -1
        && !r->discard_body
        && clcf->client_max_body_size
        && clcf->client_max_body_size < r->headers_in.content_length_n)
    {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "client intended to send too large body: %O bytes",
                      r->headers_in.content_length_n);

        r->expect_tested = 1;
        (void) ngx_http_discard_request_body(r);
        ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
        return NGX_OK;
    }

    if (rc == NGX_DONE) {
        ngx_http_clear_location(r);

        r->headers_out.location = ngx_list_push(&r->headers_out.headers);
        if (r->headers_out.location == NULL) {
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
            return NGX_OK;
        }

        r->headers_out.location->hash = 1;
        ngx_str_set(&r->headers_out.location->key, "Location");

        if (r->args.len == 0) {
            r->headers_out.location->value = clcf->name;

        } else {
            len = clcf->name.len + 1 + r->args.len;
            p = ngx_pnalloc(r->pool, len);

            if (p == NULL) {
                ngx_http_clear_location(r);
                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                return NGX_OK;
            }

            r->headers_out.location->value.len = len;
            r->headers_out.location->value.data = p;

            p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
            *p++ = '?';
            ngx_memcpy(p, r->args.data, r->args.len);
        }

        ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
        return NGX_OK;
    }

    r->phase_handler++; //下一阶段
    return NGX_AGAIN;
}

ngx_http_core_post_rewrite_phase

/*
 * NGX_HTTP_POST_REWRITE_PHASE阶段的checker方法
 */
ngx_int_t
ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
    ngx_http_phase_handler_t *ph)
{
    ngx_http_core_srv_conf_t  *cscf;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "post rewrite phase: %ui", r->phase_handler);

    if (!r->uri_changed) {
        r->phase_handler++;
        return NGX_AGAIN;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "uri changes: %d", r->uri_changes);

    /*
     * gcc before 3.3 compiles the broken code for
     *     if (r->uri_changes-- == 0)
     * if the r->uri_changes is defined as
     *     unsigned  uri_changes:4
     */

    r->uri_changes--;

    if (r->uri_changes == 0) { //url改写次数超限,结束请求
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "rewrite or internal redirection cycle "
                      "while processing \"%V\"", &r->uri);

        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
        return NGX_OK;
    }

    r->phase_handler = ph->next;

    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
    r->loc_conf = cscf->ctx->loc_conf;

    return NGX_AGAIN;
}

ngx_http_core_access_phase

/*
 * NGX_HTTP_ACCESS_PHASE阶段的checker方法
 */
ngx_int_t
ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
    ngx_int_t                  rc;
    ngx_http_core_loc_conf_t  *clcf;

    if (r != r->main) { //子请求
        r->phase_handler = ph->next; //跳到下一个阶段
        return NGX_AGAIN;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "access phase: %ui", r->phase_handler);

    rc = ph->handler(r); //执行模块挂载的handler方法

    if (rc == NGX_DECLINED) {
        r->phase_handler++; //下一个处理方法
        return NGX_AGAIN;
    }

    if (rc == NGX_AGAIN || rc == NGX_DONE) {
        return NGX_OK; //不更改r->phase_handler的值,当前处理方法有机会再次被调用。但是必须把控制权交还event模块
    }

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

    if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {

        if (rc == NGX_OK) {
            r->phase_handler++; //satisfy all, 则执行下一个handler方法
            return NGX_AGAIN;
        }

    } else { //satisfy any
        if (rc == NGX_OK) {
            r->access_code = 0;

            if (r->headers_out.www_authenticate) {
                r->headers_out.www_authenticate->hash = 0;
            }

            r->phase_handler = ph->next; //satisfy any, 则跳到下一个阶段
            return NGX_AGAIN;
        }

        if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
            if (r->access_code != NGX_HTTP_UNAUTHORIZED) {
                r->access_code = rc;
            }

            r->phase_handler++; //下一个handler方法
            return NGX_AGAIN;
        }
    }

    /* rc == NGX_ERROR || rc == NGX_HTTP_...  */

    ngx_http_finalize_request(r, rc); //结束请求
    return NGX_OK;
}

ngx_http_core_post_access_phase

/*
 * NGX_HTTP_POST_ACCESS_PHASE阶段的checker方法, 入参ph未使用,即不允许介入
 */
ngx_int_t
ngx_http_core_post_access_phase(ngx_http_request_t *r,
    ngx_http_phase_handler_t *ph)
{
    ngx_int_t  access_code;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "post access phase: %ui", r->phase_handler);

    access_code = r->access_code;

    if (access_code) { //access_code非0,表明没有访问权限
        if (access_code == NGX_HTTP_FORBIDDEN) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "access forbidden by rule");
        }

        r->access_code = 0;
        ngx_http_finalize_request(r, access_code);
        return NGX_OK;
    }

    r->phase_handler++;
    return NGX_AGAIN;
}

ngx_http_core_content_phase

/*
 * NGX_HTTP_CONTENT_PHASE阶段的checker方法
 */
ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
    ngx_http_phase_handler_t *ph)
{
    size_t     root;
    ngx_int_t  rc;
    ngx_str_t  path;

    if (r->content_handler) { //介入的特殊方式: 某location特有的handler方法, 不影响其他location
        r->write_event_handler = ngx_http_request_empty_handler;
        ngx_http_finalize_request(r, r->content_handler(r));
        return NGX_OK;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "content phase: %ui", r->phase_handler);

    rc = ph->handler(r); //执行postconfiguration钩子函数添加的handler方法

    if (rc != NGX_DECLINED) {
        ngx_http_finalize_request(r, rc);
        return NGX_OK;
    }

    /* rc == NGX_DECLINED */

    ph++;

    if (ph->checker) {
        r->phase_handler++; //下一个handler方法
        return NGX_AGAIN;
    }

    /* no content handler was found */

    if (r->uri.data[r->uri.len - 1] == '/') {

        if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "directory index of \"%s\" is forbidden", path.data);
        }

        ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
        return NGX_OK;
    }

    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");

    ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); //404
    return NGX_OK;
}

处理请求经过10个阶段

/*
 * 10个阶段处理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;

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

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

        if (rc == NGX_OK) {
            return;
        }
    }
}

记录http日志阶段特殊处理

/*
 * 记录访问日志。log阶段的handler链并不是在ngx_http_core_run_phases函数中执行, 它只需在请求处理逻辑结束后才执行一次
 */
static void
ngx_http_log_request(ngx_http_request_t *r)
{
    ngx_uint_t                  i, n;
    ngx_http_handler_pt        *log_handler;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

    log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
    n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;

    for (i = 0; i < n; i++) {
        log_handler[i](r);
    }
}