声明:
敲录:自己动手照敲录入。
nginx支持高并发,占用少量系统资源的webserver。如果听说某人会nginx模块开发,我们暗赞-------高大上。其实不然,只要你树立目标,暗下苦工,明天的你就是“高富帅”。我在2012年下半年就树立目标,研读nginx代码,工具就是GOOG,中间断断续续。到13年下半年,稍稍有点成绩,可以照葫芦画瓢,搞点小东西,原理层面的东西,并不是很理解。后来朋友推荐,看到了陶辉老师写的“深入理解Nginx”,发现很是值得我们细细品味。下面是我敲录的一个模块代码:
第一步:查看文件
[root@centos6 nginx-http-top-filter-1.1.1]# ll
total 12
-rw-r--r-- 1 root root 189 Feb 25 17:29 config
-rw-r--r-- 1 root root 5094 Mar 15 20:13 ngx_http_top_filter_module.c
第二步:编辑config配置文件
[root@centos6 nginx-http-top-filter-1.1.1]# vim config #编辑config配置文件
ngx_addon_name=ngx_http_top_filter_module
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_top_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ ngx_http_top_filter_module.c"
第三步:编写模块
[root@centos6 nginx-http-top-filter-1.1.1]# vim ngx_http_top_filter_module.c
#include
#include
#include
typedef struct {
ngx_flag_t enable;
} ngx_http_top_conf_t;
typedef struct {
ngx_int_t add_prefix;
} ngx_http_top_ctx_t;
static void *ngx_http_top_create_conf(ngx_conf_t *cf);
static char *ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child);
static ngx_int_t ngx_http_top_filter_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_topfilter_header_filter(ngx_http_request_t *r);
static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in);
static ngx_str_t filter_prefix = ngx_string("[my filter prefix]");
/*----step------3--------*/
static ngx_command_t ngx_http_top_filter_commands[] = {
{ ngx_string("add_prefix"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_top_conf_t,enable),
NULL },
ngx_null_command
};
/*----step------2--------*/
static ngx_http_module_t ngx_http_top_filter_module_ctx = {
NULL, /* proconfiguration */
ngx_http_top_filter_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_top_create_conf, /* create location configuration */
ngx_http_top_merge_conf /* merge location configuration */
};
/*-----step-------1--------------------------*/
ngx_module_t ngx_http_top_filter_module = {
NGX_MODULE_V1,
&ngx_http_top_filter_module_ctx, /* module context */
ngx_http_top_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
/*----step----4----------------*/
static ngx_int_t
ngx_http_topfilter_header_filter(ngx_http_request_t *r)
{
ngx_http_top_ctx_t *ctx;
ngx_http_top_conf_t *conf;
if(r->headers_out.status != NGX_HTTP_OK){
return ngx_http_next_header_filter(r);
}
ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);
if(ctx){
return ngx_http_next_header_filter(r);
}
conf = ngx_http_get_module_loc_conf(r, ngx_http_top_filter_module);
if(conf->enable ==0){
return ngx_http_next_header_filter(r);
}
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_top_ctx_t));
if(ctx == NULL){
return NGX_ERROR;
}
ctx->add_prefix = 0;
ngx_http_set_ctx(r, ctx, ngx_http_top_filter_module);
/*注意测试文件后缀必须是.txt,如果是html,需要将红色部分修改,原因自己想想,会明白的,当时我测试的时候,也想了一下。 */
if(r->headers_out.content_type.len >= sizeof(" text/plain") -1 && ngx_strncasecmp(r->headers_out.content_type.data, (u_
char *) "text/plain", sizeof("text/plain") -1) ==0){
ctx->add_prefix = 1;
if(r->headers_out.content_length_n > 0)
{
r->headers_out.content_length_n += filter_prefix.len;
}
}
return ngx_http_next_header_filter(r);
}
static void *ngx_http_top_create_conf(ngx_conf_t *cf)
{
ngx_http_top_conf_t *mycf;
mycf = (ngx_http_top_conf_t *)ngx_pcalloc(cf->pool, sizeof(ngx_http_top_conf_t));
if (mycf == NULL) {
return NULL;
}
mycf->enable= NGX_CONF_UNSET;
return mycf;
}
static char *
ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_top_conf_t *prev = (ngx_http_top_conf_t *)parent;
ngx_http_top_conf_t *conf = (ngx_http_top_conf_t *)child;
ngx_conf_merge_value(conf->enable, prev->enable, 0);
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_top_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_topfilter_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_topfilter_body_filter;
return NGX_OK;
}
static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_http_top_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);
if(ctx == NULL){
return ngx_http_next_body_filter(r, in);
}
ctx->add_prefix = 2;
ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len);
b->pos = filter_prefix.data;
b->last = b->pos + filter_prefix.len;
b->start = b->pos;
ngx_chain_t *c1 = ngx_alloc_chain_link(r->pool);
if (c1 == NULL )
{
return NGX_ERROR;
}
c1->buf = b;
c1->next = in;
return ngx_http_next_body_filter(r, c1);
}
文档中的数字标号,是我自己搞的标注,方便阅读用的。线上环l境中用的一个nginx修改版,最近在想怎样通过模块的方式实现,但是还没搞好,改天搞好以后,再贴到这里。
敲录:自己动手照敲录入。
nginx支持高并发,占用少量系统资源的webserver。如果听说某人会nginx模块开发,我们暗赞-------高大上。其实不然,只要你树立目标,暗下苦工,明天的你就是“高富帅”。我在2012年下半年就树立目标,研读nginx代码,工具就是GOOG,中间断断续续。到13年下半年,稍稍有点成绩,可以照葫芦画瓢,搞点小东西,原理层面的东西,并不是很理解。后来朋友推荐,看到了陶辉老师写的“深入理解Nginx”,发现很是值得我们细细品味。下面是我敲录的一个模块代码:
第一步:查看文件
[root@centos6 nginx-http-top-filter-1.1.1]# ll
total 12
-rw-r--r-- 1 root root 189 Feb 25 17:29 config
-rw-r--r-- 1 root root 5094 Mar 15 20:13 ngx_http_top_filter_module.c
第二步:编辑config配置文件
[root@centos6 nginx-http-top-filter-1.1.1]# vim config #编辑config配置文件
ngx_addon_name=ngx_http_top_filter_module
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_top_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ ngx_http_top_filter_module.c"
第三步:编写模块
[root@centos6 nginx-http-top-filter-1.1.1]# vim ngx_http_top_filter_module.c
#include
#include
#include
typedef struct {
ngx_flag_t enable;
} ngx_http_top_conf_t;
typedef struct {
ngx_int_t add_prefix;
} ngx_http_top_ctx_t;
static void *ngx_http_top_create_conf(ngx_conf_t *cf);
static char *ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child);
static ngx_int_t ngx_http_top_filter_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_topfilter_header_filter(ngx_http_request_t *r);
static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in);
static ngx_str_t filter_prefix = ngx_string("[my filter prefix]");
/*----step------3--------*/
static ngx_command_t ngx_http_top_filter_commands[] = {
{ ngx_string("add_prefix"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_top_conf_t,enable),
NULL },
ngx_null_command
};
/*----step------2--------*/
static ngx_http_module_t ngx_http_top_filter_module_ctx = {
NULL, /* proconfiguration */
ngx_http_top_filter_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_top_create_conf, /* create location configuration */
ngx_http_top_merge_conf /* merge location configuration */
};
/*-----step-------1--------------------------*/
ngx_module_t ngx_http_top_filter_module = {
NGX_MODULE_V1,
&ngx_http_top_filter_module_ctx, /* module context */
ngx_http_top_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
/*----step----4----------------*/
static ngx_int_t
ngx_http_topfilter_header_filter(ngx_http_request_t *r)
{
ngx_http_top_ctx_t *ctx;
ngx_http_top_conf_t *conf;
if(r->headers_out.status != NGX_HTTP_OK){
return ngx_http_next_header_filter(r);
}
ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);
if(ctx){
return ngx_http_next_header_filter(r);
}
conf = ngx_http_get_module_loc_conf(r, ngx_http_top_filter_module);
if(conf->enable ==0){
return ngx_http_next_header_filter(r);
}
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_top_ctx_t));
if(ctx == NULL){
return NGX_ERROR;
}
ctx->add_prefix = 0;
ngx_http_set_ctx(r, ctx, ngx_http_top_filter_module);
/*注意测试文件后缀必须是.txt,如果是html,需要将红色部分修改,原因自己想想,会明白的,当时我测试的时候,也想了一下。 */
if(r->headers_out.content_type.len >= sizeof(" text/plain") -1 && ngx_strncasecmp(r->headers_out.content_type.data, (u_
char *) "text/plain", sizeof("text/plain") -1) ==0){
ctx->add_prefix = 1;
if(r->headers_out.content_length_n > 0)
{
r->headers_out.content_length_n += filter_prefix.len;
}
}
return ngx_http_next_header_filter(r);
}
static void *ngx_http_top_create_conf(ngx_conf_t *cf)
{
ngx_http_top_conf_t *mycf;
mycf = (ngx_http_top_conf_t *)ngx_pcalloc(cf->pool, sizeof(ngx_http_top_conf_t));
if (mycf == NULL) {
return NULL;
}
mycf->enable= NGX_CONF_UNSET;
return mycf;
}
static char *
ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_top_conf_t *prev = (ngx_http_top_conf_t *)parent;
ngx_http_top_conf_t *conf = (ngx_http_top_conf_t *)child;
ngx_conf_merge_value(conf->enable, prev->enable, 0);
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_top_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_topfilter_header_filter;
ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_topfilter_body_filter;
return NGX_OK;
}
static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_http_top_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);
if(ctx == NULL){
return ngx_http_next_body_filter(r, in);
}
ctx->add_prefix = 2;
ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len);
b->pos = filter_prefix.data;
b->last = b->pos + filter_prefix.len;
b->start = b->pos;
ngx_chain_t *c1 = ngx_alloc_chain_link(r->pool);
if (c1 == NULL )
{
return NGX_ERROR;
}
c1->buf = b;
c1->next = in;
return ngx_http_next_body_filter(r, c1);
}
文档中的数字标号,是我自己搞的标注,方便阅读用的。线上环l境中用的一个nginx修改版,最近在想怎样通过模块的方式实现,但是还没搞好,改天搞好以后,再贴到这里。