4.3.4 预设配置项处理方法的工作原理
在4.2.4节中可以看到,自定义的配置项处理方法读取参数值也是很简单的,直接使用ngx_str_t*value=cf->args->elts;就可以获取参数。接下来将把参数赋值到ngx_http_mytest_conf_t结构体的相应成员中。不过,预设的配置项处理方法并不知道每个HTTP模块所定义的结构体包括哪些成员,那么,它们怎么可以做到具有通用性的呢?
很简单,返回到4.2.2节就可以看到,ngx_command_t结构体的offset成员已经进行了正确的设置(实际存储参数的成员相对于整个结构体的偏移位置),Nginx配置项解析模块在调用ngx_command_t结构体的set回调方法时,会同时把offset偏移位置传进来。每种预设的配置项解析方法都只解析特定的数据结构,也就是说,它们既知道存储参数的成员相对于整个结构体的偏移量,又知道这个成员的数据类型,自然可以做到具有通用性了。
下面以读取数字配置项的方法ngx_conf_set_num_slot为例,说明预设的14个通用方法是如何解析配置项的。
charngx_conf_set_num_slot(ngx_conf_tcf,ngx_command_tcmd,voidconf)
{
//指针conf就是存储参数的结构体的地址
char*p=conf;
ngx_int_t*np;
ngx_str_t*value;
ngx_conf_post_t*post;
/根据ngx_command_t中的offset偏移量,可以找到结构体中的成员,而对于ngx_conf_set_num_slot方法而言,存储数字的必须是ngx_int_t类型/
np=(ngx_int_t*)(p+cmd->offset);
/在这里可以知道为什么要把使用ngx_conf_set_num_slot方法解析的成员在create_loc_conf等方法中初始化为NGX_CONF_UNSET,否则是会报错的/
if(*np!=NGX_CONF_UNSET){
return"is duplicate";
}
//value将指向配置项的参数
value=cf->args->elts;
/将字符串的参数转化为整型,并设置到create_loc_conf等方法生成的结构体的相关成员上/
*np=ngx_atoi(value[1].data,value[1].len);
if(*np==NGX_ERROR){
return"invalid number";
}
//如果ngx_command_t中的post已经实现,那么还需要调用post->post_handler方法
if(cmd->post){
post=cmd->post;
return post->post_handler(cf,post,np);
}
return NGX_CONF_OK;
}
可以看到,这是一种非常灵活和巧妙的设计。