4.2.5 合并配置项

回顾一下4.1节中的例子,一个test_str配置同时在http{……}、server{……}、location/url1{……}中出现时,到底以哪一个为准?本节将讨论如何合并不同配置块间的同名配置项,首先回顾一下4.2.1节中ngx_http_module_t的结构。


typedef struct{

……

voidcreate_loc_conf)(ngx_conf_t*cf);

charmerge_loc_conf)(ngx_conf_tcf,voidprev,void*conf);

……

}ngx_http_module_t;


上面这段代码定义了create_loc_conf方法,意味着HTTP框架会建立loc级别的配置。什么意思呢?就是说,如果没有实现merge_loc_conf方法,也就是在构造ngx_http_module_t时将merge_loc_conf设为NULL了,那么在4.1节的例子中server块或者http块内出现的配置项都不会生效。如果我们希望在server块或者http块内的配置项也生效,那么可以通过merge_loc_conf方法来实现。merge_loc_conf会把所属父配置块的配置项与子配置块的同名配置项合并,当然,如何合并取决于具体的merge_loc_conf实现。

merge_loc_conf有3个参数,第1个参数仍然是ngx_conf_tcf,提供一些基本的数据结构,如内存池、日志等。我们需要关注的是第2、第3个参数,其中第2个参数voidprev是指解析父配置块时生成的结构体,而第3个参数void*conf则指出的是保存子配置块的结构体。

仍以4.1节的例子为例,来看看如何合并同时出现了6次的test_str配置项,如下所示。


static char*

ngx_http_mytest_merge_loc_conf(ngx_conf_tcf,voidparent,void*child)

{

ngx_http_mytest_conf_tprev=(ngx_http_mytest_conf_t)parent;

ngx_http_mytest_conf_tconf=(ngx_http_mytest_conf_t)child;

ngx_conf_merge_str_value(conf->my_str,

prev->my_str,"defaultstr");

return NGX_CONF_OK;

}


可以看到,只需要按照自己的需求将父配置块的值赋予子配置块即可,这时表示父配置块优先级更高,反过来也是可以的,表示子配置块的优先级更高。例如,在解析server{……}块时(传入的child参数就是当前server块的ngx_http_mytest_conf_t结构),父配置块(也就是传入的parent参数)就是http{……}块;解析location{……}块时父配置块就是server{……}块。

如何处理父、子配置块下的同名配置项,每个HTTP模块都可以自由选择。例如,可以简单地以父配置替换子配置,或者将两种不同级别的配置做完运算后再覆盖等。上面的例子对不同级别下的test_str配置项的处理是最简单的,下面我们使用Nginx预置的ngx_conf_merge_str_value宏来合并子配置块中ngx_str_t类型的my_str成员,看看ngx_conf_merge_str_value到底做了哪些事情。


define ngx_conf_merge_str_value(conf,prev,default)\

//当前配置块中是否已经解析到test_str配置项

if(conf.data==NULL){\

//父配置块中是否已经解析到test_str配置项

if(prev.data){\

//将父配置块中的test_str参数值直接覆盖当前配置块的test_str

conf.len=prev.len;\

conf.data=prev.data;\

}else{\

/如果父配置块和子配置块都没有解析到test_str,以default参数作为默认值传给当前配置块的test_str/

conf.len=sizeof(default)-1;\

conf.data=(u_char*)default;\

}

\

}


事实上,Nginx预设的配置项合并方法有10个,它们的行为与上述的ngx_conf_merge_str_value是相似的。参见表4-5中Nginx已经实现好的10个简单的配置项合并宏,它们的参数类型与ngx_conf_merge_str_value一致,而且除了ngx_conf_merge_bufs_value外,它们都将接收3个参数,分别表示父配置块参数、子配置块参数、默认值。

4.2.5 合并配置项 - 图1

在4.3.3节中我们会看到HTTP框架在什么时候会调用各模块的merge_loc_conf方法或者merge_srv_conf方法。