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;

}


可以看到,这是一种非常灵活和巧妙的设计。