NGX_CONF_2MORE: 指令至少读入2个参数
这里还有很多其他的选项:. 结构体成员 set 是一个函数指针,它指向的函数用来进行模块配置;这个设定函数一般用来将配置文件中的参数传递给程序,并保存在配置结构体中。设定函数有三个入参:指向结构体 ngx_conf_t 的指针, 这个结构体里包含需要传递给指令的参数
指向结构体 ngx_command_t 的指针
指向模块自定义配置结构体的指针
设定函数会在遇到指令时执行,Nginx提供了多个函数用来保存特定类型的数据,这些函数包含有:ngx_conf_set_flag_slot: 将 "on" or "off" 转换成 1 or 0
ngx_conf_set_str_slot: 将字符串保存为 ngx_str_t
ngx_conf_set_num_slot: 解析一个数字并保存为int
ngx_conf_set_size_slot: 解析一个数据大小(如:"8k", "1m") 并保存为size_t
当然还有其他的,在中很容易查到。如果你觉得现有这些内置的函数还不能满足你,当然也可以传入自己的函数引用。 这些内置函数是如何知道把数据存放在哪里的呢?这就是接下来两个结构体成员 conf 和 offset要做的事了. conf 告诉Nginx把数据存在模块的哪个配置中,是main配置、server 配置, 还是 location 配置 ?(通过 NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET, 或者 NGX_HTTP_LOC_CONF_OFFSET). offset 确定到底是保存在结构体的哪个位置。 最后, post指向模块在读配置的时候需要的一些零碎变量。一般它是NULL。 ngx_command_t数组以ngx_null_command 为终结符(就好像字符串以'\0'为终结符一样). 3.3. 模块上下文 静态的ngx_http_module_t结构体,包含一大坨函数引用,用来创建和合并三段配置(main,server,location),命名方式一般是:ngx_http_<module name>_module_ctx. 这些函数引用依次是:preconfiguration 在读入配置前调用
postconfiguration 在读入配置后调用
create_main_conf 在创建main配置时调用(比如,用来分配空间和设置默认值)
init_main_conf 在初始化main配置时调用(比如,把原来的默认值用nginx.conf读到的值来覆盖)
init_main_conf 在创建server配置时调用
merge_srv_conf 合并server和main配置时调用
create_loc_conf 创建location配置时调用
merge_loc_conf 合并location和server配置时调用
函数的入参各不相同,取决于他们具体要做的事情。这里是结构体的具体定义: typedefstruct{ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
void*(*create_main_conf)(ngx_conf_t *cf);
char*(*init_main_conf)(ngx_conf_t *cf,void*conf);
void*(*create_srv_conf)(ngx_conf_t *cf);
char*(*merge_srv_conf)(ngx_conf_t *cf,void*prev,void*conf);
void*(*create_loc_conf)(ngx_conf_t *cf);
char*(*merge_loc_conf)(ngx_conf_t *cf,void*prev,void*conf);
} ngx_http_module_t; 可以把你不需要的函数设置为NULL,Nginx会忽略掉他们。 绝大多数的 handler只使用最后两个: 一个用来为特定location配置来分配内存,(叫做 ngx_http_<module name>_create_loc_conf), 另一个用来设定默认值以及合并继承过来的配置值(叫做 ngx_http_<module name >_merge_loc_conf)。合并函数同时还会检查配置的有效性,如果有错误,则server的启动将被挂起。 下面是一个使用模块上下文结构体的例子: static ngx_http_module_t ngx_http_circle_gif_module_ctx ={
NULL,/* preconfiguration */
NULL,/* postconfiguration */
NULL,/* create main configuration */
NULL,/* init main configuration */
NULL,/* create server configuration */
NULL,/* merge server configuration */
ngx_http_circle_gif_create_loc_conf,/* create location configuration */
ngx_http_circle_gif_merge_loc_conf /* merge location configuration */
}; 现在开始讲得更深一点。这些配置回调函数看其来很像,所有模块都一样,而且Nginx的API都会用到这个部分,所以值得好好看看。 3.3.1. create_loc_conf 下面这段摘自我自己写的模块circle_gif(源代码),create_loc_conf的骨架大概就是这个样子. 它的入参是(ngx_conf_t),返回值是更新了的模块配置结构体(在这里是 ngx_http_circle_gif_loc_conf_t). staticvoid*
ngx_http_circle_gif_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_circle_gif_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool,sizeof(ngx_http_circle_gif_loc_conf_t));
if(conf == NULL){
return NGX_CONF_ERROR;
}
conf->min_radius = NGX_CONF_UNSET_UINT;
conf->max_radius = NGX_CONF_UNSET_UINT;
return conf;
} 首先需要指出的是Nginx的内存分配;只要使用了 ngx_palloc(malloc的一个包装函数)或者 ngx_pcalloc (calloc的包装函数),就不用担心内存的释放了。(TODO: to see why?) UNSET可能的常量有NGX_CONF_UNSET_UINT, NGX_CONF_UNSET_PTR, NGX_CONF_UNSET_SIZE, NGX_CONF_UNSET_MSEC,以及无所不包的NGX_CONF_UNSET,UNSET让合并函数知道哪些变量是需要覆盖的。 3.3.2. merge_loc_conf 下面的例子是我的模块circle_gif中的合并函数: staticchar*
ngx_http_circle_gif_merge_loc_conf(ngx_conf_t *cf,void*parent,void*child)
{
ngx_http_circle_gif_loc_conf_t *prev = parent;
ngx_http_circle_gif_loc_conf_t *conf = child;
ngx_conf_merge_uint_value(conf->min_radius, prev->min_radius,10);
ngx_conf_merge_uint_value(conf->max_radius, prev->max_radius,20);
if(conf->min_radius <1){
ngx_conf_log_error(NGX_LOG_EMERG, cf,0,
"min_radius must be equal or more than 1");
return NGX_CONF_ERROR;
}
if(conf->max_radius < conf->min_radius){
ngx_conf_log_error(NGX_LOG_EMERG, cf,0,
"max_radius must be equal or more than min_radius");
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
} 这里的需要注意的是Nginx提供了一些好用的合并函数用来合并不同类型的数据(ngx_conf_merge_<data type>_value),这类函数的入参是:
当前location的变量值
如果第一个参数没有被设置而采用的值