// 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;
}
ngx_http_merge_servers和ngx_http_merge_locations註釋
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.