最近在看Nginx源码,这篇blog中会给出一个简单的实例。在编写Nginx module时主要编写的是两个结构:一个是上下文结构表明编写的是什么模块(例如:ngx_http_module_t),另一个是命令模块(ngx_command_t)。
下面细致的说下这两个module,加深记忆吧:
-
typedef struct{
-
/*着两个函数分别于解析配置文件前和解析之后各自调用*/
-
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
-
Ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
-
-
/*一个函数用于存储main_srv_conf配置选项,另一个用于初始化main_srv_conf*/
-
void *(*create_main_conf)(ngx_conf_t *cf);
-
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
-
-
/*一个函数用于存储loc_srv_conf配置选项,另一个用于合并main_srv_conf和loc_srv_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;
-
/*
-
下面以最后了两项为例进行简要说明:
-
create_loc_conf为location{...}配置项分配内存
-
merge_loc_conf用于合并loc_conf和srv_conf同名配置,具体的合并方式系统给出来了一些宏,例如ngx_conf_merge_value、ngx_conf_ptr_value等
-
*/
-
typedef struct{
-
ngx_str_t name;
-
Ngx_uint_t type;
-
char *(*set)(ngx_cong_t* cf, ngx_command_t* cmd, void *conf);
-
ngx_uint_t conf;
-
ngx_uint_t offset;
-
void *post; //一个补充字段,一般不用的,填入NULL
-
}ngx_command_t;
-
/*
-
type:表示在读到哪些模配置项{main_conf,serv_conf,loc_conf}的name配置,以及参数类型和个数。例如:NGX_HTTP_LOC_CONG|NGX_CONF_TAKE1,表示配置只能出现在 location{...},且只能携带一个参数。
-
conf:表示配置项是由ngx_http_module_t结构中的哪个函数(create_loc、srv、main_conf)创建的。例如下面的例子中定义了 location配置,此时就应该由ngx_http_module_t中的create_loc_conf分配结构内存。
-
offset:表示要读取的配置项(name),在结构中的位置。以便调用系统默认的set函数时,必须设置这个值,但自定义set函数则不必要。
-
set:读取到name配置项的时候,进行处理配置项的回调函数,这些回调函数一共有14个,下面给出一些并作简要说明:
-
ngx_conf_set_flag_slot:将“on”或者“off”转换成1或0;
-
ngx_conf_set_str_slot:将字符串保存为ngx_str_t;
-
ngx_conf_set_num_slot:解析一个数字并保存为ngx_int_t;
-
见下面的具体实例
-
*/
-
//下面给出一个简单的实例,并进行注释说明。
-
-
typedef struct{
-
ngx_str_t test;
-
}ngx_http_hello_loc_conf_t;
-
-
/*用于读取loc_src_conf中的配置信息,并存储在ngx_http_hello_loc_conf_t中*/
-
static char *ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-
-
static ngx_command_t ngx_http_hello_commands[] = {
-
{ ngx_string("hello"),
-
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
-
ngx_http_hello,
-
0,
-
0,
-
NULL },
-
ngx_string("test"),
-
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
-
ngx_conf_set_str_slot,
-
NGX_HTTP_LOC_CONF_OFFSET,
-
offsetof(ngx_http_hello_loc_conf_t, test),
-
NULL},
-
ngx_null_command //表示数组结束
-
};
-
/*此函数用于读取到配置问时,执行的回调函数*/
-
static void *ngx_http_hello_create_loc_conf(ngx_conf_t *cf);
-
static ngx_http_module_t ngx_http_hello_module_ctx = {
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
ngx_http_hello_create_loc_conf, // 用于为ngx_http_hello_loc_conf_t结构分配内存
-
NULL
-
};
-
ngx_module_t ngx_http_hello_module = {
-
NGX_MODULE_V1,
-
&ngx_http_hello_module_ctx, // 模块上下文
-
ngx_http_hello_commands, // 模块指令集
-
NGX_HTTP_MODULE,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NULL,
-
NGX_MODULE_V1_PADDING
-
};
-
static u_char ngx_hello_string[] = "hello world";
-
/*
-
处理函数,主要是当处理到NGX_HTTP_CONTENT_PHASE阶段时,进行的回调处理,比如返回用户的请求信息时。
-
*/
-
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r){
-
ngx_int_t rc;
-
ngx_buf_t *b;
-
ngx_chain_t out;
-
ngx_http_hello_loc_conf_t *hrcf;
-
/* 设置响应内容格式,这里为text/html */
-
r->headers_out.content_type_len = sizeof("text/html") - 1;
-
r->headers_out.content_type.len = sizeof("text/html") - 1;
-
r->headers_out.content_type.data = (u_char *) "text/html";
-
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
-
if (b == NULL) {
-
return NGX_HTTP_INTERNAL_SERVER_ERROR;
-
}
-
out.buf = b;
-
out.next = NULL;
-
b->pos = ngx_hello_string;
-
b->last = ngx_hello_string + sizeof(ngx_hello_string) - 1;
-
b->memory = 1;
-
b->last_buf = 1;
-
r->headers_out.status = NGX_HTTP_OK;
-
r->headers_out.content_length_n = sizeof(ngx_hello_string) - 1;
-
//应答HTTP的header信息
-
rc = ngx_http_send_header(r);
-
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
-
return rc;
-
}
-
/* 演示如何获取配置选项的值 */
-
hrcf = ngx_http_get_module_loc_conf(r, ngx_http_hello_module);
-
printf("test: %s\n", hrcf->test.data);
-
return ngx_http_output_filter(r, &out);//应答HTTP CONTENT信息
-
}
-
/* 读取局部配置信息 */
-
static void *ngx_http_hello_create_loc_conf(ngx_conf_t *cf){
-
ngx_http_hello_loc_conf_t *hlcf;
-
hlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_hello_loc_conf_t));
-
if (hlcf == NULL) {
-
return NULL;
-
}
-
return hlcf;
-
}
-
static char *ngx_http_hello(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_hello_handler; /* 设置读取到NGX_HTTP_CONTENT_PHASE 的回调函数 */
-
return NGX_CONF_OK;
-
}
本文出处:
http://blog.chinaunix.net/uid-28311809-id-4198428.html
阅读(2977) | 评论(0) | 转发(0) |