nginx的HTTP模块编写
2015-01-24 10:50
204 查看
本文是学习《深入理解nginx -- 模块开发与架构解析》的读书笔记
nginx的模块分为4个大类型的模块:
事件模块
HTTP模块
邮件代理相关的mail模块
其他模块
进行configure时,--add-module=PATH是一样的。
定义了模块的上下文结构
定义了模块命令结构
这样之后才是模块的上下文和模块定义:
ngx_http_myfilter_module_ctx
ngx_http_myfilter_module
从模块上下文可以看出,过滤功能在模块完成配置项处理后开始,其初始化方法为ngx_myfilter_init()。
触发命令的回调函数
至此,一个http模块就可以完成了。
ngx_addon_name=ngx_http_mytest_module
HTTP_MODULES="HTTP M ODULESngx h ttp m ytest m odule"NGX A DDON S RCS=" NGX_ADDON_SRCS
$ngx_addon_dir/ngx_http_mytest_module.c"
HTTP_MODULES是设置HTTP需要加载的模块列表,在具体编译的时候会生成modules的数组,然后根据数组的先后顺序一个一个加载
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/core/ngx_conf_file.h
里面的ngx_module_s的结构
最主要记得是要设置上下文结构ctx和命令集commands
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/http/ngx_http_config.h
这个结构是如果需要的话在读取,重载配置文件的时候定义的8个阶段
create_main_conf
create_srv_conf
create_loc_conf
preconfiguration
init_main_conf
merge_srv_conf
merge_loc_conf
postconfiguration
它的结构说明看:
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/core/ngx_conf_file.h
里面碰到的set回调函数,这个回调函数可以使用nginx预设的14个解析配置方法,或者使用自定义的方法
14个预设的解析配置方法有:
ngx_conf_set_flag_slot
ngx_conf_set_str_slot
ngx_conf_set_str_array_slot
ngx_conf_set_keyval_slot
ngx_conf_set_num_slot
ngx_conf_set_size_slog
ngx_conf_set_off_slot
ngx_conf_set_msec_slot
ngx_conf_set_sec_slot
ngx_conf_set_bufs_slot
ngx_conf_set_enum_slot
ngx_conf_set_bitmask_slot
ngx_conf_set_acccess_slot
ngx_conf_set_path_slot
如果使用了上面的14个解析配置方法,就可以不用自己写这个方法了
如果是自己写这个配置解析方法,就需要写第六步
ngx_http_mytest_handler
它的函数定义如下:
static ngx_init_t ngx_http_mytest_handler(ngx_http_request_t *r)
使用ngx_http_request_t指针输入
在ngx_http_request指针中也可以设置HTTP返回
它的结构说明看:
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/http/ngx_http_request.h
nginx的模块分为4个大类型的模块:
事件模块
HTTP模块
邮件代理相关的mail模块
其他模块
开发HTTP模块流程
这里的HTTP模块是最简单最经常编写的模块,开发一个完整的简单的HTTP模块需要下面几个步骤(以模块名为ngx_http_mytest_module为例):1 编写config文件(这是为了让nginx在configure过程能找到编写的模块)
下面是编写具体的模块代码结构ngx_addon_name=ngx_http_mytest_module | |
HTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module" | |
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c" |
编写一个HTTP过滤模块
以向返回给用户的文本格式响应包体前加一段字符串"[my filter prefix]"为例,展示如何编写一个HTTP过滤模块。源代码来自于《深入理解Nginx》。1.config文件的编写
与前几篇博文的HTTP模块不同,HTTP过滤模块需要HTTP_FILTER_MODULES一项以把所有过滤模块一同编译,因此config写作:ngx_addon_name=ngx_http_myfilter_module HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_myfilter_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_myfilter_module.c"
进行configure时,--add-module=PATH是一样的。
2 编写模块结构 ngx_http_mytest_module
这个是模块结构,其中起的作用是:定义了模块的上下文结构
定义了模块命令结构
ngx_module_t ngx_http_mytest_module = { | |
NGX_MODULE_V1, | |
&ngx_http_mytest_module_ctx, | |
ngx_http_mytest_commands, | |
NGX_HTTP_MODULE, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NGX_MODULE_V1_PADDING | |
}; |
3 编写模块上下文结构 ngx_http_mytest_module_ctx
这个结构的意思就是nginx在触发了模块运行的时候,如何处理已经在其他http,server,location定义过的上下文static ngx_http_module_t ngx_http_mytest_module_ctx = { | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL | |
}; |
static ngx_http_module_t ngx_http_myfilter_module_ctx = { NULL, ngx_http_myfilter_init, NULL, NULL, NULL, NULL, ngx_http_myfilter_create_conf, ngx_http_myfilter_merge_conf };
ngx_http_myfilter_module_ctx
ngx_module_t ngx_http_myfilter_module = { NGX_MODULE_V1, &ngx_http_myfilter_module_ctx, ngx_http_mytest_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING };
ngx_http_myfilter_module
从模块上下文可以看出,过滤功能在模块完成配置项处理后开始,其初始化方法为ngx_myfilter_init()。
4 编写模块命令结构 ngx_http_mytest_commands
这个结构的意思就是nginx在配置文件中触发了哪些命令,其中指定了:触发命令的回调函数
static ngx_command_t ngx_http_mytest_commands[] = { | ||||
{ | ||||
ngx_string("mytest"), | ||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS, | ||||
ngx_http_mytest,/*
| ||||
NGX_HTTP_LOC_CONF_OFFSET, | ||||
0, | ||||
NULL | ||||
}, | ||||
ngx_null_command | ||||
}; |
5 触发命令的回调函数 ngx_http_mytest
这个回调函数中可以设置对http请求的具体处理方法static char * | |
ngx_http_mytest(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_mytest_handler; | |
return NGX_CONF_OK; | |
} |
6 对http请求的具体处理方法 ngx_http_mytest_handler
这个方法的参数中可以获取http请求结构,并且可以设置http返回至此,一个http模块就可以完成了。
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) | |
{ | |
if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { | |
return NGX_HTTP_NOT_ALLOWED; | |
} | |
ngx_int_t rc = ngx_http_discard_request_body(r); | |
if (rc != NGX_OK) { | |
return rc; | |
} | |
ngx_str_t type = ngx_string("text/plain"); | |
ngx_str_t response = ngx_string("Hello World"); | |
r->headers_out.status = NGX_HTTP_OK; | |
r->headers_out.content_length_n = response.len; | |
r->headers_out.content_type = type; | |
rc = ngx_http_send_header(r); | |
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
return rc; | |
} | |
ngx_buf_t *b; | |
b = ngx_create_temp_buf(r->pool, response.len); | |
if (b == NULL) { | |
return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
} | |
ngx_memcpy(b->pos, response.data, response.len); | |
b->last = b->pos + response.len; | |
b->last_buf = 1; | |
ngx_chain_t out; | |
out.buf = b; | |
out.next = NULL; | |
return ngx_http_output_filter(r, &out); | |
} |
对应的各个步骤说明:
1 编写config文件
示例:ngx_addon_name=ngx_http_mytest_module
HTTP_MODULES="HTTP M ODULESngx h ttp m ytest m odule"NGX A DDON S RCS=" NGX_ADDON_SRCS
$ngx_addon_dir/ngx_http_mytest_module.c"
HTTP_MODULES是设置HTTP需要加载的模块列表,在具体编译的时候会生成modules的数组,然后根据数组的先后顺序一个一个加载
2 ngx_http_mytest_module的结构类型是ngx_module_t
它的结构说明看:https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/core/ngx_conf_file.h
里面的ngx_module_s的结构
最主要记得是要设置上下文结构ctx和命令集commands
3 某块上下文ngx_http_mytest_module_ctx的结构类型是ngx_http_module_t
它的结构说明看:https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/http/ngx_http_config.h
这个结构是如果需要的话在读取,重载配置文件的时候定义的8个阶段
create_main_conf
create_srv_conf
create_loc_conf
preconfiguration
init_main_conf
merge_srv_conf
merge_loc_conf
postconfiguration
4 ngx_http_mytest_commands 是一个ngx_command_s的数组
ngx_command_s的结构说明看:它的结构说明看:
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/core/ngx_conf_file.h
里面碰到的set回调函数,这个回调函数可以使用nginx预设的14个解析配置方法,或者使用自定义的方法
14个预设的解析配置方法有:
ngx_conf_set_flag_slot
ngx_conf_set_str_slot
ngx_conf_set_str_array_slot
ngx_conf_set_keyval_slot
ngx_conf_set_num_slot
ngx_conf_set_size_slog
ngx_conf_set_off_slot
ngx_conf_set_msec_slot
ngx_conf_set_sec_slot
ngx_conf_set_bufs_slot
ngx_conf_set_enum_slot
ngx_conf_set_bitmask_slot
ngx_conf_set_acccess_slot
ngx_conf_set_path_slot
5 触发命令的回调函数的解析配置方法格式如下:
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);如果使用了上面的14个解析配置方法,就可以不用自己写这个方法了
如果是自己写这个配置解析方法,就需要写第六步
ngx_http_mytest_handler
它的函数定义如下:
static ngx_init_t ngx_http_mytest_handler(ngx_http_request_t *r)
使用ngx_http_request_t指针输入
在ngx_http_request指针中也可以设置HTTP返回
它的结构说明看:
https://github.com/jianfengye/nginx-1.0.14_comment/blob/master/src/http/ngx_http_request.h
一个具体的例子:
https://github.com/jianfengye/MyWorks/tree/master/nginx_module_mytest/* | |
* Copyright (C) yejianfeng | |
*/ | |
#include <ngx_config.h> | |
#include <ngx_core.h> | |
#include <ngx_http.h> | |
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r); | |
static char * | |
ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
static ngx_command_t ngx_http_mytest_commands[] = { | |
{ | |
ngx_string("mytest"), | |
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS, | |
ngx_http_mytest, | |
NGX_HTTP_LOC_CONF_OFFSET, | |
0, | |
NULL | |
}, | |
ngx_null_command | |
}; | |
static ngx_http_module_t ngx_http_mytest_module_ctx = { | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL | |
}; | |
ngx_module_t ngx_http_mytest_module = { | |
NGX_MODULE_V1, | |
&ngx_http_mytest_module_ctx, | |
ngx_http_mytest_commands, | |
NGX_HTTP_MODULE, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NGX_MODULE_V1_PADDING | |
}; | |
static char * | |
ngx_http_mytest(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_mytest_handler; | |
return NGX_CONF_OK; | |
} | |
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) | |
{ | |
if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { | |
return NGX_HTTP_NOT_ALLOWED; | |
} | |
ngx_int_t rc = ngx_http_discard_request_body(r); | |
if (rc != NGX_OK) { | |
return rc; | |
} | |
ngx_str_t type = ngx_string("text/plain"); | |
ngx_str_t response = ngx_string("Hello World"); | |
r->headers_out.status = NGX_HTTP_OK; | |
r->headers_out.content_length_n = response.len; | |
r->headers_out.content_type = type; | |
rc = ngx_http_send_header(r); | |
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
return rc; | |
} | |
ngx_buf_t *b; | |
b = ngx_create_temp_buf(r->pool, response.len); | |
if (b == NULL) { | |
return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
} | |
ngx_memcpy(b->pos, response.data, response.len); | |
b->last = b->pos + response.len; | |
b->last_buf = 1; | |
ngx_chain_t out; | |
out.buf = b; | |
out.next = NULL; | |
return ngx_http_output_filter(r, &out); | |
} |
相关文章推荐
- Nginx编写HTTP模块:第一个Nginx HTTP模块 “Hello World!”
- nginx 编写简单HTTP模块以及nginx http handler的hello world示例编写
- nginx 编写简单HTTP模块 hello world
- nginx的HTTP模块编写
- nginx的HTTP模块编写
- Nginx编写HTTP模块:“Hello World”的第二种写法(HTTP模块介入阶段的2种方法)
- Nginx源码分析与实践---(一)编写一个简单的Http模块
- 编写nginx的http模块需要注意一些细节
- nginx编写http模块编译报错
- 解读nginx第三方模块ngx_http_auth_request_module
- 高性能Web服务器Nginx的配置与部署研究(9)核心模块之HTTP模块基本常用指令
- 高性能Web服务器Nginx的配置与部署研究(10)核心模块之HTTP模块Location相关指令
- 详细解释:nginx中ngx_http_access_module模块(HTTP Access 模块)配置及各个参数含义
- nginx模块学习——nginx_http_push_module模块深入讲解和聊天室实现
- 详细解释:nginx中ngx_http_auth_basic_module模块(HTTP Auth Basic 模块)配置及各个参数含义 .
- nginx源码分析(2)——http模块的初始化过程
- 详细解释:nginx中ChsHttpProxyModule模块各项配置及其含义
- 解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现
- 解剖Nginx·模块开发篇(2)ngx_http_hello_world_module 模块基本结构定义
- nginx自定义模块编写-根据post参数路由到不同服务器