当前位置:Gxlcms > PHP教程 > NginxHTTP过滤模块开发

NginxHTTP过滤模块开发

时间:2021-07-01 10:21:17 帮助过:28人阅读

Nginx 过滤模块

HTTP过滤模块的开发步骤

  1. 确定源代码文件名称;
  2. 创建config脚本,当执行configure时将该目录添加进去;
  3. 定义过滤模块,实例化ngx_module_t类型的模块结构;
  4. 通过设置ngx_module_t结构中的ngx_command_t数组来处理感兴趣的配置项;
  5. 实现初始化函数,初始化方法就是将ngx_http_output_header_filter_t和ngx_http_output_body_filter_t函数插入到过滤模块链表的首部;
  6. 实现ngx_http_output_header_filter_pt和ngx_http_output_body_filter_pt函数;
  7. 编译安装后,修改nginx.conf配置文件中的过滤模块选项,开启与否。

配置脚本

ngx_add

HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_myfilter_module"
NGX_ADD>"$NGX_ADDON_SRCS$ngx_addon_dir/ngx_http_myfilter_module.c"

模块内容

#include <../src/core/ngx_config.h>#include <../src/core/ngx_core.h>#include <../src/http/ngx_http.h>//Declarestatic ngx_int_t ngx_http_myfilter_header_filter(ngx_http_request_t *);
static ngx_int_t ngx_http_myfilter_body_filter(ngx_http_request_t*,ngx_chain_t*);
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;


//On/Offtypedefstruct {
    ngx_flag_t enable;
}ngx_http_myfilter_conf_t;

staticvoid *ngx_http_myfilter_create_conf(ngx_conf_t *cf){
    ngx_http_myfilter_conf_t *mycf;

    //Allocate memory
    mycf = (ngx_http_myfilter_conf_t*)ngx_pcalloc(cf->pool,sizeof(ngx_http_myfilter_conf_t));
    if(mycf == NULL)
        returnNULL;

    mycf->enable = NGX_CONF_UNSET;

    return mycf;
}

staticchar *
ngx_http_myfilter_merge_conf(ngx_conf_t *cf,void *parent,void *child){
    ngx_http_myfilter_conf_t *prev = (ngx_http_myfilter_conf_t*)parent;
    ngx_http_myfilter_conf_t *conf = (ngx_http_myfilter_conf_t*)child;
    ngx_conf_merge_value(conf->enable,prev->enable,0);
    return NGX_CONF_OK;
}

/* ------------------------------------------- *///State for prefixtypedefstruct {
    /* add_prefix = 
     * 0    the filter module is off
     * 1    can add prefix
     * 2    has been added prefix already
     */
    ngx_int_t add_prefix;
} ngx_http_myfilter_ctx_t;

//Analyse configurestatic ngx_command_t
ngx_http_myfilter_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_myfilter_conf_t,enable),
        NULL},
    ngx_null_command
};

static ngx_int_t
ngx_http_myfilter_init(ngx_conf_t *cf){
    //Insert before the first node
    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_myfilter_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_myfilter_body_filter;

    return NGX_OK;
}

/* ------------------------------------------- *///Parsestatic 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
};

/* ------------------------------------------- *///Module information
ngx_module_t ngx_http_myfilter_module = {
    NGX_MODULE_V1,
    &ngx_http_myfilter_module_ctx,
    ngx_http_myfilter_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};

/* ------------------------------------------- */static ngx_str_t filter_prefix = ngx_string("[my filter module]");

//Filter to process the headerstatic ngx_int_t
ngx_http_myfilter_header_filter(ngx_http_request_t *r){
    ngx_http_myfilter_ctx_t *ctx;
    ngx_http_myfilter_conf_t *conf;

    if(r->headers_out.status != NGX_HTTP_OK){
        return ngx_http_next_header_filter(r);
    }

    //Get context
    ctx = ngx_http_get_module_ctx(r,ngx_http_myfilter_module);
    if(ctx){
        return ngx_http_next_header_filter(r);
    }

    //Get configure by ngx_http_myfilter_conf_t
    conf = ngx_http_get_module_loc_conf(r,ngx_http_myfilter_module);

    if(conf->enable == 0){//add_prefix offreturn ngx_http_next_header_filter(r);
    }

    //Create ngx_http_myfilter_ctx_t
    ctx = ngx_pcalloc(r->pool,sizeof(ngx_http_myfilter_ctx_t));
    if(ctx == NULL){
        return NGX_ERROR;
    }

    //add_prefix = 0 express do not add prefix
    ctx->add_prefix = 0;

    //Set context
    ngx_http_set_ctx(r,ctx,ngx_http_myfilter_module);

    //myfilter module only figure out Content-Type="text/plain"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){
        //Set add_prefix
        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);
}

//Filter to process the bodystatic ngx_int_t
ngx_http_myfilter_body_filter(ngx_http_request_t *r,ngx_chain_t *in){
    ngx_http_myfilter_ctx_t *ctx;
    ctx = ngx_http_get_module_ctx(r,ngx_http_myfilter_module);
    //If cannot get context or the add_prefix is 0/2,do not processif(ctx == NULL || ctx->add_prefix !=1)
        return ngx_http_next_body_filter(r,in);

    //To make sure never add prefix again
    ctx->add_prefix = 2;

    //Get prefix string
    ngx_buf_t *b = ngx_create_temp_buf(r->pool,filter_prefix.len);
    b->start = b->pos = filter_prefix.data;
    b->last = b->pos + filter_prefix.len;

    //Get and set ngx_chain_t list at the bginning
    ngx_chain_t *cl = ngx_alloc_chain_link(r->pool);
    cl->buf = b;
    cl->next = in;

    return ngx_http_next_body_filter(r,cl);
}

配置文件nginx.conf

在http{}中加上
add_prefix on;
开启过滤模块

编译

./configure --add-module=模块路径/
make
make install

HTTP过滤模块也是HTTP模块,所以HTTP模块的书写大致也是这样。

版权声明:Pain is just in your mind.

以上就介绍了Nginx HTTP过滤模块开发,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

人气教程排行