设为首页 收藏本站
查看: 570|回复: 0

[经验分享] nginx模块开发入门(四)-2.3 The Module Context

[复制链接]

尚未签到

发表于 2016-12-28 07:03:47 | 显示全部楼层 |阅读模式
2.3. 模块上下文(The Module Context)
    静态的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配置时调用
函数的入参各不相同,取决于他们具体要做的事情。这里http/ngx_http_config.h是结构体的具体定义:
typedef struct {
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都会用到这个部分,所以值得好好看看。

2.3.1. create_loc_conf

    下面这段摘自我自己写的模块circle_gif(源代码),create_loc_conf的骨架大概就是这个样子. 它的入参是(ngx_conf_t),返回值是更新了的模块配置结构体(在这里是 ngx_http_circle_gif_loc_conf_t).

static void *
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的包装函数),就不用担心内存的释放了。
UNSET可能的常量有NGX_CONF_UNSET_UINT, NGX_CONF_UNSET_PTR, NGX_CONF_UNSET_SIZE, NGX_CONF_UNSET_MSEC, 以及无所不包的NGX_CONF_UNSET,UNSET让合并函数知道哪些变量是需要覆盖的。

2.3.2. merge_loc_conf

    下面的例子是我的模块circle_gif中的合并函数:

static char *
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),这类函数的入参是:

ngx_conf_merge_uint_value(conf->min_radius, prev->min_radius, 10);

   1. 当前location 的变量值
   2. 如果第一个参数没有被设置而采用的值
   3. 如果第一第二个参数都没有被设置而采用的值
   结果会被保存在第一个参数中。能用的合并函数包括 ngx_conf_merge_size_value, ngx_conf_merge_msec_value 等等. 可参见 core/ngx_conf_file.h.
引用

问: 第一个参数是传值的,那如何能做到将结果保存到第一个参数中?
答: 这些函数都是由预处理命令定义的(在真正编译之前,它们会被扩展成一些if语句)


   同时还需要注意的是错误的产生。函数会往log文件写一些东西,同时返回NGX_CONF_ERROR。这个返回值会将server的启动挂起。(因为被标示为NGX_LOG_EMERG级别,所以错误同时还会输出到标准输出。作为参考,core/ngx_log.h列出了所有的日志级别。)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-320285-1-1.html 上篇帖子: Nginx设置alias实现虚拟目录 alias与root的用法区别 下篇帖子: Nginx技术交流Q群:225942451(探讨安装、部署、模块开发、源码分析,及其他知名服务端开源软件)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表