Nginx HTTP フィルター モジュールの開発

WBOY
リリース: 2016-08-08 09:20:18
オリジナル
1082 人が閲覧しました

Nginxフィルターモジュール

HTTPフィルターモジュールの開発手順

  1. ソースコードファイルの名前を決定する;
  2. 構成スクリプトを作成し、configureの実行時にディレクトリを追加する;
  3. フィルターモジュールを定義し、モジュールをインスタンス化するngx_module_t 構造体;
  4. ngx_module_t 構造体に ngx_command_t 配列を設定して、対象の構成項目を処理します。 初期化方法は、ngx_http_output_header_filter_t 関数と ngx_http_output_body_filter_t 関数をフィルター モジュール リストの先頭に挿入することです。
  5. ngx_http_output_header_ filter_pt 関数と ngx_http_output_body_filter_pt 関数を実装します。
  6. コンパイルとインストール後、nginx.conf 設定ファイルのフィルター モジュール オプションを変更して有効にするかどうかを設定します。
設定スクリプト
<code>ngx_add

HTTP_FILTER_MODULES=<span>"<span>$HTTP_FILTER_MODULES</span> ngx_http_myfilter_module"</span>
NGX_ADD>"<span>$NGX_ADDON_SRCS</span><span>$ngx_addon_dir</span>/ngx_http_myfilter_module.c"</code>
ログイン後にコピー

モジュールコンテンツ

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


<span>//On/Off</span><span>typedef</span><span>struct</span> {
    ngx_flag_t enable;
}ngx_http_myfilter_conf_t;

<span>static</span><span>void</span> *ngx_http_myfilter_create_conf(ngx_conf_t *cf){
    ngx_http_myfilter_conf_t *mycf;

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

    mycf->enable = NGX_CONF_UNSET;

    <span>return</span> mycf;
}

<span>static</span><span>char</span> *
ngx_http_myfilter_merge_conf(ngx_conf_t *cf,<span>void</span> *parent,<span>void</span> *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,<span>0</span>);
    <span>return</span> NGX_CONF_OK;
}

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

<span>//Analyse configure</span><span>static</span> ngx_command_t
ngx_http_myfilter_commands[]={
    {ngx_string(<span>"add_prefix"</span>),
        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),
        <span>NULL</span>},
    ngx_null_command
};

<span>static</span> ngx_int_t
ngx_http_myfilter_init(ngx_conf_t *cf){
    <span>//Insert before the first node</span>
    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;

    <span>return</span> NGX_OK;
}

<span>/* ------------------------------------------- */</span><span>//Parse</span><span>static</span> ngx_http_module_t
ngx_http_myfilter_module_ctx = {
    <span>NULL</span>,
    ngx_http_myfilter_init,
    <span>NULL</span>,
    <span>NULL</span>,
    <span>NULL</span>,
    <span>NULL</span>,
    ngx_http_myfilter_create_conf,
    ngx_http_myfilter_merge_conf
};

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

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

<span>//Filter to process the header</span><span>static</span> 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;

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

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

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

    <span>if</span>(conf->enable == <span>0</span>){<span>//add_prefix off</span><span>return</span> ngx_http_next_header_filter(r);
    }

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

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

    <span>//Set context</span>
    ngx_http_set_ctx(r,ctx,ngx_http_myfilter_module);

    <span>//myfilter module only figure out Content-Type="text/plain"</span><span>if</span>(r->headers_out<span>.content_type</span><span>.len</span>>=<span>sizeof</span>(<span>"text/plain"</span>) - <span>1</span> &&
            ngx_strncasecmp(r->headers_out<span>.content_type</span><span>.data</span>,(u_char*)<span>"text/plain"</span>,<span>sizeof</span>(<span>"text/plain"</span>)-<span>1</span>)==<span>0</span>){
        <span>//Set add_prefix</span>
        ctx->add_prefix = <span>1</span>;
        <span>if</span>(r->headers_out<span>.content_length_n</span>><span>0</span>)
            r->headers_out<span>.content_length_n</span> += filter_prefix<span>.len</span>;
    }
        <span>return</span> ngx_http_next_header_filter(r);
}

<span>//Filter to process the body</span><span>static</span> 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);
    <span>//If cannot get context or the add_prefix is 0/2,do not process</span><span>if</span>(ctx == <span>NULL</span> || ctx->add_prefix !=<span>1</span>)
        <span>return</span> ngx_http_next_body_filter(r,in);

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

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

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

    <span>return</span> ngx_http_next_body_filter(r,cl);
}</code>
ログイン後にコピー

設定ファイルnginx.conf

httpに

を追加します。{} add_prefix をオンにします。 フィルターモジュールをオンにする


Compile

<code>./configure --<span>add</span>-<span>module</span>=模块路径/
make
make install</code>
ログイン後にコピー

HTTPフィルターモジュールもHTTPモジュールなので、HTTPモジュールは大まかにこんな感じで書きます。


著作権声明: 痛みはあなたの心の中にあるだけです。

上記では、Nginx HTTP フィルタリング モジュールの開発についてその側面も含めて紹介しましたが、PHP チュートリアルに興味のある友人に役立つことを願っています。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート