码迷,mamicode.com
首页 > 其他好文 > 详细

ngx_http_hello

时间:2014-09-19 11:39:55      阅读:304      评论:0      收藏:0      [点我收藏+]

标签:des   cWeb   style   http   io   os   使用   ar   strong   

tengine.taobao.org/book/chapter_03.html

程序解析:

1,核心是定义三个结构体,分别是

angx_command_t(模块的配置结构):由于定义了自己的配置结构体

typedef struct

{

ngx_str_t hello_string;

ngx_int_t hello_counter;

}ngx_http_hello_loc_conf_t

结构体中有两个配置项,所以需要同步定义两个获取配置信息的函数

static char *ngx_http_hello_string(ngx_conf_t *cf, ngx_command_t *cmd,

void *conf);

static char *ngx_http_hello_counter(ngx_conf_t *cf, ngx_command_t *cmd,

void *conf);

一个创建配置信息结构体的函数(采取动态内存分配)

static void *ngx_http_hello_create_loc_conf(ngx_conf_t *cf);

以及一个合并配置信息结构体的函数

static char *ngx_http_hello_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ;

两个获取配置信息的函数作为ngx_command_t结构体数组的set成员,创建配置结构体和合并配置结构体的函数作为ngx_http_module_t的成员存在


bngx_http_mocule_tHTTP模块通用接口,也是模块上下文):结构体本身由8个回调函数指针构成,本次示例中定义了两个,第一个用来挂载,第二个用来创建配置结构体。


cngx_module_t(模块的定义):包含了上面两个结构体以及模块类型。



2,实现模块的加载,有两种加载方式:按处理阶段加载和按需加载。前者一般选取在NGX_HTTP_CONTENT_PHASE阶段加载,设置方式是在结构体ngx_http_module_t中设置回调方法。后者则在结构体ngx_command_t中的函数指针set指向的函数内部定义配置项结构体,HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时,如果请求与配置项所在的配置块匹配,就调用配置结构体的handler成员处理这个请求。给出两个实例:

按处理阶段加载

static ngx_int_t

ngx_http_hello_init(ngx_conf_t *cf)

{

ngx_http_handler_pt *h;

ngx_http_core_main_conf_t *cmcf;

cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);

if (h == NULL) {

return NGX_ERROR;

}

*h = ngx_http_hello_handler;

return NGX_OK;

}

注(函数原型):ngx_http_config.h:#define ngx_http_conf_get_module_main_conf(cf, module)


按需加载

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;

}

ngx_http_core_loc_conf_t结构体是第一个HTTP模块ngx_http_core_module模块的create_loc_conf方法生成的,它对应者当前解析的location块,它的handler成员即是被执行的处理方法。

注:ngx_http_conf_get_module_loc_conf函数原型同上。有一点需要注意的就是,在加载时获取配置结构体用的函数是ngx_http_conf_get_module_xxx(main, srv, loc)_conf,而在处理函数中获取配置结构体采用的是ngx_http_get_module_xxx(main, srv, loc)_conf函数。函数原型分别为:

#define ngx_http_conf_get_module_main_conf(cf, module) \

((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]

#define ngx_http_conf_get_module_srv_conf(cf, module) \

((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]

#define ngx_http_conf_get_module_loc_conf(cf, module) \

((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]


#define ngx_http_get_module_loc_conf(r, module) (r)->loc_conf[module.ctx_index]


使用按处理阶段加载方式需要注意一点,加载函数中定义的配置结构体是ngx_http_core_main_conf_tnginx没有定义结构体ngx_http_core_loc_conf_t,只有main_conf_t结构体中才定义了阶段数组成员

ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1];

因此,尽管自定义的配置项是在location块中出现的,只要使用按处理阶段加载的方式,都只能使用ngx_http_core_main_conf_t结构体。


本示例采用按处理阶段加载方式,并且调用预定义的配置解析函数来设置ngx_comman_tset成员,加载和配置解析分开。采用按需加载的一种较简单模式是将ngx_http_module_t8个回调方法全部设置为NULL,设置set函数指针为自定义的配置解析函数,并在函数体内设置handler方法,这样在配置解析完后就会调用匹配的handler



3,实现handler函数,也就是所有的处理工作,包括:从ngx_http_request_t中读取配置信息并处理,判断HTTP方法并决定是否响应,决定是否丢弃收到的包体,发送响应头,发送响应包体。由以下函数实现功能:


#define ngx_http_get_module_loc_conf(r, module) (r)->loc_conf[module.ctx_index]

获取配置信息,并进行处理,比如配置项hello_counteroffUNSET的情况。


if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD)))

如果是不支持的方法,直接返回NGX_HTTP_NOTALLOWED


ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r);

本示例中不需要对包体进行处理,所以丢弃。


ngx_int_t ngx_http_send_header(ngx_http_request_t *r)

如果request方法是head,那么在执行完这一步后就返回。

发送头部有两种方法,本示例利用request_t中的headers_out成员,直接设置后发送。也可以自定义HTTP头部,然后加入到headers链表。


ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain)

将内存中的字符串作为包体发送,利用ngx_buf_t携带字符串信息。可以利用函数

ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);

来简化ngx_buf_t的创建过程,size参数表示为ngx_buf_tdata成员分配的空间,比如字符串“hello”长度为5,那么size参数就为5

如果使用ngx_pcalloc的话,参数size就应该是sizeof(ngx_buf_t)ngx_buf_t结构体中的posstart等成员都是指针,所以先给结构体指针分配一个内存,对于字符串(ngx_buf_t指针指向的内容)的存储需要再次调用ngx_pcalloc进行分配,函数ngx_create_temp_buf只是将上面两步合并了而已。

如下是ngx_buf_t的内存结构图:

bubuko.com,布布扣




 

 

 

 

在发送内存数据时,如果不设置ngx_buf_tlast_buf成员为1的话,浏览器会一直处于正在连接状态,而nginx则永远不会发送数据给客户端,过了几分钟才出现找不到服务器。


比较奇葩的一个问题是我第一次运行ngx_http_mytest_module模块时,浏览器是接收的数据,然后另存为。而再次运行则变成了直接显示在浏览器上面了。


在发送文件的时候总是出现Not found,后来发现是文件权限问题,即客户端对文件没有读权限导致不能正常打开文件,确定的方法是在程序中添加perror函数,这样,错误就被输出到log文件中去了。

ngx_http_hello

标签:des   cWeb   style   http   io   os   使用   ar   strong   

原文地址:http://www.cnblogs.com/yxl10/p/3734543.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!