ngx_http_merge_servers和ngx_http_merge_locations註釋

// cf 由http框架傳進去,主要用到其ctx成員,此成員指向的是解析http{}生成的ngx_http_conf_ctx_t
// cmcf ngx_http_core_module在http{}級別下生成的配置項結構體,ngx_http_core_main_conf_t
// module 當前要合併配置項的http模塊的八個回調函數結構體
// ctx_index 當前http模塊在ngx_http_conf_ctx_t的配置項結構體的數組下標
static char *
ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
    ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    char                        *rv;
    ngx_uint_t                   s;
    ngx_http_conf_ctx_t         *ctx, saved;
    ngx_http_core_loc_conf_t    *clcf;
    ngx_http_core_srv_conf_t   **cscfp;

    cscfp = cmcf->servers.elts; // 所有server{}的ngx_http_core_srv_conf_t
    ctx = (ngx_http_conf_ctx_t *) cf->ctx; // 全局ngx_http_conf_ctx_t
    saved = *ctx; 
    rv = NGX_CONF_OK;
    // 每個server{}都有一個ngx_http_core_srv_conf_t
    // 這個結構體內部成員ctx指向其所屬server{}生成的ngx_http_conf_ctx_t
    for (s = 0; s < cmcf->servers.nelts; s++) {

        /* merge the server{}s' srv_conf's */

        ctx->srv_conf = cscfp[s]->ctx->srv_conf; // 當前server{}的srv_conf
                                                 // 將全局的srv_conf替換了
                                                 // 保證後續合併server{}和location{}
                                                 // 最後會重新替換回saved

        // 開始合併http{}的srv_conf和server{}的srv_conf                                                        
        if (module->merge_srv_conf) { 
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
                                        cscfp[s]->ctx->srv_conf[ctx_index]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }

        if (module->merge_loc_conf) {

            /* merge the server{}'s loc_conf */

            ctx->loc_conf = cscfp[s]->ctx->loc_conf; // 替換ctx->loc_conf 
                                                     // 後續合併會更改其值

            // 合併http{}的loc_conf和server{}的loc_conf和server
            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
                                        cscfp[s]->ctx->loc_conf[ctx_index]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }

            /* merge the locations{}' loc_conf's */
            // 合併當前server{}與其下的location{}的配置項結構體
            // clcf是ngx_http_core_module在當前server{}生成的ngx_http_core_loc_conf_t
            clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

            rv = ngx_http_merge_locations(cf, clcf->locations,
                                          cscfp[s]->ctx->loc_conf,
                                          module, ctx_index);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }
    }

failed:

    *ctx = saved; // 最後需要替換會原值

    return rv;
}


// cf 同上
// locations 鏈表頭
// loc_conf location{}直系屬的塊(可能是server{},也有可能是location{})的loc_conf
// module 當前模塊的八個回調函數結構體
// ctx_index 同上
static char *
ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    char                       *rv;
    ngx_queue_t                *q;
    ngx_http_conf_ctx_t        *ctx, saved;
    ngx_http_core_loc_conf_t   *clcf;
    ngx_http_location_queue_t  *lq;

    // 當前塊其內部沒有額外的locations{}塊
    if (locations == NULL) {
        return NGX_CONF_OK;
    }
    // 這裏的ctx已經由http{}和server{}合併過了
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
    saved = *ctx;

    // 遍歷此鏈表,等於遍歷當前要合併的塊下所有第一級locations{}塊
    for (q = ngx_queue_head(locations);
         q != ngx_queue_sentinel(locations);
         q = ngx_queue_next(q))
    {
        lq = (ngx_http_location_queue_t *) q; 

        clcf = lq->exact ? lq->exact : lq->inclusive; // exact表示精確匹配, inclusive是正則匹配
                                                      // 指向的是其對應的location{}塊中由ngx_http_core_module生產的ngx_http_core_loc_conf_t
                                                      // 這個結構體內部有一個成員loc_conf,指向的是location{}生產的ngx_http_conf_ctx_t的loc_conf

        ctx->loc_conf = clcf->loc_conf; // 再次會修改cf->ctx 
                                        // 保證後續遞歸合併location{}的location{}能夠有上層合併後的配置項結構體
                                        // 最後遞歸完需要修改回來

        rv = module->merge_loc_conf(cf, loc_conf[ctx_index], // 合併
                                    clcf->loc_conf[ctx_index]);
        if (rv != NGX_CONF_OK) {
            return rv;
        }

        rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf, // 遞歸合併
                                      module, ctx_index);
        if (rv != NGX_CONF_OK) {
            return rv;
        }
    }

    *ctx = saved; // 最後需要替換會原值

    return NGX_CONF_OK;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章