天天看點

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

typedef struct {

    ngx_flag_t enable;

} ngx_http_top_conf_t;

    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){

    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;

        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 )

    {

    c1->buf = b;

    c1->next = in;

    return ngx_http_next_body_filter(r, c1);

       文檔中的數字标号,是我自己搞的标注,友善閱讀用的。線上環l境中用的一個nginx修改版,最近在想怎樣通過子產品的方式實作,但是還沒搞好,改天搞好以後,再貼到這裡。

繼續閱讀