nginx模块开发-入门篇
日期:2014-05-09 18:32:38
最后更新日期:2015-07-07 15:28:40
1.定义模块用于配置的一个数据结构,该数据结构主要是映射配置文件里面配置指令的不同参数。demo模块该结构定义的如下:
[code lang="cpp"]
typedef struct {
ngx_flag_t enable;
}ngx_http_accesskey_loc_conf_t;
[/code]
2.定义一个命令数组,该数组主要说明本模块支持的配置命令。demo模块的命令数组:
[code lang="cpp"]
static ngx_command_t ngx_http_accesskey_commands[]={
{
ngx_string("accesskey"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_accesskey_loc_conf_t,enable),
NULL
},
ngx_null_command
};
[/code]
demo模块就支持一个命令-accesskey。用来决定是否打开效验。nginx的ngx_command_t结构定义:
[code lang="cpp"]
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
[/code]
注:
将ngx_http_accesskey_commands数组第一个元素内的值对号入座,可以猜出个大概。name表示命令名。type表示该命令类型,由支持的作用域以及该命令的后跟几个参数决定,NGX_CONF_FLAG表示命令后面接一个参数,该参数为FLAG类型。set表示解析配置文件时,遇到这条命令后解析的回调函数。回调函数ngx_conf_set_flag_slot函数的意思就是将on转化为1,off转为0。而offsetof(ngx_http_accesskey_loc_conf_t,enable)的意思表示将accesskey的参数值存储于ngx_http_accesskey_loc_conf_t结构的enable里面。post表示额外的参数信息指针。
3.定义context上下文。
[code lang="cpp"]
static ngx_http_module_t ngx_http_accesskey_module_ctx = {
NULL,
ngx_http_accesskey_init,
NULL,
NULL,
NULL,
NULL,
ngx_http_accesskey_create_loc_conf,
ngx_http_accesskey_merge_loc_conf
};
[/code]
context上下文指示一系列初始化时机需要的函数,不需要则填NULL即可。ngx_http_accesskey_init表示模块初始化时调用的函数。由于demo模块是http access phase阶段处理的,ngx_http_accesskey_init函数内需要注册该模块。
[code lang="cpp"]
static ngx_int_t ngx_http_accesskey_init(ngx_conf_t *cf){
ngx_log_error(NGX_LOG_INFO, cf->log, 0, "\n ngx_http_accesskey_init \n");
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_ACCESS_PHASE].handlers);
if( h==NULL ){
ngx_log_error(NGX_LOG_INFO,cf->log,0,"\n error ngx_http_accesskey_init \n");
return NGX_ERROR;
}
*h = ngx_http_accesskey_handler;
return NGX_OK;
[/code]
注册后,也就是每个请求的http access phase时候,需要调用demo模块的ngx_http_accesskey_handler函数。
4.定义模块类型变量。
[code lang="cpp"]
ngx_module_t ngx_http_accesskey_module = {
NGX_MODULE_V1,
&ngx_http_accesskey_module_ctx,
ngx_http_accesskey_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
[/code]
上诉执行了type为http module和模块的上下文以及命令数组。其他值为一个宏,现在可以忽略掉。ngx_module_t类型如下:
[code lang="cpp"]
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
[/code]
5.http access phase过程
前面说过,请求过来后,会调用demo模块ngx_http_accesskey_handler。该函数逻辑很简单,当配置文件里面为accesskey on时,那么enable的值为1,accesskey off时,enable值为0。
[code lang="cpp"]
static ngx_int_t ngx_http_accesskey_handler(ngx_http_request_t* r) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "\"ngx_http_accesskey_handler, args=%V\"", &r->args);
ngx_http_accesskey_loc_conf_t *alcf;
alcf = ngx_http_get_module_loc_conf(r,ngx_http_accesskey_module);
if( !alcf->enable ){
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "\n off \n");
return NGX_OK;
}
return NGX_HTTP_FORBIDDEN;
}
[/code]
6.最后看到的效果就是accesskey打开时,就是403,关闭时就可以正常浏览。更改/usr/local/nginx/conf/nginx.conf的根目录location里面指令:
[code lang="cpp"]
location / {
accesskey on;
root html;
index index.html index.htm;
}
[/code]
访问首页效果如下:

7.进阶
可以继续查看网上开源第三方开源accesskey模块
测试代码:
https://github.com/acjog/nginx/tree/master/accesskey_demo