http://www.oschina.net/question/12_4180
配置解析
配置设定函数一般用来将配置文件中的参数传递给程序,并保存在配置结构体中。设定函数有三个入参:
1. 指向结构体 ngx_conf_t 的指针, 这个结构体里包含需要传递给指令的参数
2. 指向结构体 ngx_command_t 的指针
3. 指向模块自定义配置结构体的指针
设定函数会在遇到指令时执行,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
当然还有其他的,在core/ngx_conf_file.h中很容易查到。如果你觉得现有这些内置的函数还不能满足你,当然也可以传入自己的函数引用。
模块上下文
静态的ngx_http_module_t结构体,包含一大坨函数引用,用来创建和合并三段配置 (main,server,location),命名方式一般是:ngx_http_<module name>_module_ctx. 这些函数引用依次是:
preconfiguration:
在创建和读取该模块的配置信息之前被调用。
postconfiguration:
在创建和读取该模块的配置信息之后被调用。
create_main_conf:
调用该函数创建本模块位于http block的配置信息存储结构。该函数成功的时候,返回创建的配置对象。失败的话,返回NULL。
init_main_conf:调用该函数初始化本模块位于http block的配置信息存储结构。该函数成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。
create_srv_conf:
调用该函数创建本模块位于http server block的配置信息存储结构,每个server block会创建一个。该函数成功的时候,返回创建的配置对象。失败的话,返回NULL。
merge_srv_conf:因为有些配置指令即可以出现在http block,也可以出现在http server block中。那么遇到这种情况,每个server都会有自己存储结构来存储该server的配置,但是在这种情况下当在http block中的配置与server block中的配置信息冲突的时候,就需要调用此函数进行合并,该函数并非必须提供,当预计到绝对不会发生需要合并的情况的时候,就无需提供。当然为了安全期间还是建议提供。该函数成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。
create_loc_conf:
调用该函数创建本模块位于location block的配置信息存储结构。每个在配置中指明的location创建一个。该函数成功的时候,返回创建的配置对象。失败的话,返回NULL。
merge_loc_conf:与merge_srv_conf类似,这个也是进行配置值合并的地方。该函数成功的时候,返回NGX_CONF_OK。失败的话,返回NGX_CONF_ERROR或错误字符串。
函数的入参各不相同,取决于他们具体要做的事情。
绝大多数的 handler只使用最后两个: 一个用来为特定location配置来分配内存,(叫做 ngx_http_<module name>_create_loc_conf), 另一个用来设定默认值以及合并继承过来的配置值(叫做 ngx_http_<module name >_merge_loc_conf)。合并函数同时还会检查配置的有效性,如果有错误,则server的启动将被挂起。
Handlers
一个handler处理的结果通常有三种情况。处理成功,处理失败(处理的时候发生了错误)或者是拒绝去处理。在拒绝处理的情况下,这个location的处理就会由默认的handler来进行处理。
Handler一般做4件事:获取location配置;生成合适的响应;发送响应头;发送响应体。Handler有一个参数,即请求结构体。
获取location配置
这部分只需要调用 ngx_http_get_module_loc_conf,传入当前请求的结构体和模块定义即可。下面是我的circle gif handler的相关部分:
static ngx_int_t
ngx_http_circle_gif_handler(ngx_http_request_t *r)
{
ngx_http_circle_gif_loc_conf_t *circle_gif_config;
circle_gif_config = ngx_http_get_module_loc_conf(r, ngx_http_circle_gif_module);
...
现在我们就可以访问之前在合并函数中设置的所有变量了。
生成响应
发送响应体
现在模块已经生成了一个响应,并存放在了内存中。接下来它需要将这个响应分配给一个特定的缓冲区,然后把这个缓冲区加入到链表,然后调用链表中“发送响应体”的函数。
链表在这里起什么作用呢?Nginx 中,handler模块(其实filter模块也是)生成响应到buffer中是同时完成的;链表中的每个元素都有指向下一个元素的指针,如果是NULL 则说明链表到头了。简单起见,我们假设只有一个buffer。
Handler的装载
Handler的装载通过往模块启用了的指令的回调函数中添加代码来完成。
Handler的装载通过往模块启用了的指令的回调函数中添加代码来完成。比如,我的circle gif 中ngx_command_t是这样的:
{ ngx_string("circle_gif"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_circle_gif,
0,
0,
NULL }
回调函数是里面的第三个元素,在这个例子中就是那个ngx_http_circle_gif。回调函数的参数是由指令结构体(ngx_conf_t, 包含用户配置的参数),相应的ngx_command_t结构体以及一个指向模块自定义配置结构体的指针组成的。我的circle gif模块中,这些函数是这样子的:
static char *
ngx_http_circle_gif(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_circle_gif_handler;
return NGX_CONF_OK;
}
这里可以分为两步:首先,得到当前location的“core”结构体,再分配给它一个handler。
http://wiki.nginx.org/3rdPartyModules
http://code.google.com/p/emillers-guide-to-nginx-module-chn/wiki/NginxModuleDevGuide_CHN