Nginx 過濾模塊簡(jiǎn)介

2022-03-23 15:49 更新

過濾模塊簡(jiǎn)介

執(zhí)行時(shí)間和內(nèi)容

過濾(filter)模塊是過濾響應(yīng)頭和內(nèi)容的模塊,可以對(duì)回復(fù)的頭和內(nèi)容進(jìn)行處理。它的處理時(shí)間在獲取回復(fù)內(nèi)容之后,向用戶發(fā)送響應(yīng)之前。它的處理過程分為兩個(gè)階段,過濾 HTTP 回復(fù)的頭部和主體,在這兩個(gè)階段可以分別對(duì)頭部和主體進(jìn)行修改。

在代碼中有類似的函數(shù):

ngx_http_top_header_filter(r);
ngx_http_top_body_filter(r, in);

就是分別對(duì)頭部和主體進(jìn)行過濾的函數(shù)。所有模塊的響應(yīng)內(nèi)容要返回給客戶端,都必須調(diào)用這兩個(gè)接口。

執(zhí)行順序

過濾模塊的調(diào)用是有順序的,它的順序在編譯的時(shí)候就決定了??刂凭幾g的腳本位于 auto/modules 中,當(dāng)你編譯完 Nginx 以后,可以在 objs 目錄下面看到一個(gè) ngx_modules.c 的文件。打開這個(gè)文件,有類似的代碼:

        ngx_module_t *ngx_modules[] = {
            ...
            &ngx_http_write_filter_module,
            &ngx_http_header_filter_module,
            &ngx_http_chunked_filter_module,
            &ngx_http_range_header_filter_module,
            &ngx_http_gzip_filter_module,
            &ngx_http_postpone_filter_module,
            &ngx_http_ssi_filter_module,
            &ngx_http_charset_filter_module,
            &ngx_http_userid_filter_module,
            &ngx_http_headers_filter_module,
            &ngx_http_copy_filter_module,
            &ngx_http_range_body_filter_module,
            &ngx_http_not_modified_filter_module,
            NULL
        };

從 write_filter 到 not_modified_filter,模塊的執(zhí)行順序是反向的。也就是說最早執(zhí)行的是 not_modified_filter,然后各個(gè)模塊依次執(zhí)行。一般情況下,第三方過濾模塊的 config 文件會(huì)將模塊名追加到變量 HTTP_AUX_FILTER_MODULES 中,此時(shí)該模塊只能加入到 copy_filter 和 headers_filter 模塊之間執(zhí)行。

Nginx 執(zhí)行的時(shí)候是怎么按照次序依次來執(zhí)行各個(gè)過濾模塊呢?它采用了一種很隱晦的方法,即通過局部的全局變量。比如,在每個(gè) filter 模塊,很可能看到如下代碼:

        static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
        static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;

        ...

        ngx_http_next_header_filter = ngx_http_top_header_filter;
        ngx_http_top_header_filter = ngx_http_example_header_filter;

        ngx_http_next_body_filter = ngx_http_top_body_filter;
        ngx_http_top_body_filter = ngx_http_example_body_filter;

ngx_http_top_header_filter 是一個(gè)全局變量。當(dāng)編譯進(jìn)一個(gè) filter 模塊的時(shí)候,就被賦值為當(dāng)前 filter 模塊的處理函數(shù)。而 ngx_http_next_header_filter 是一個(gè)局部全局變量,它保存了編譯前上一個(gè) filter 模塊的處理函數(shù)。所以整體看來,就像用全局變量組成的一條單向鏈表。

每個(gè)模塊想執(zhí)行下一個(gè)過濾函數(shù),只要調(diào)用一下 ngx_http_next_header_filter 這個(gè)局部變量。而整個(gè)過濾模塊鏈的入口,需要調(diào)用 ngx_http_top_header_filter 這個(gè)全局變量。ngx_http_top_body_filter 的行為與 header fitler 類似。

響應(yīng)頭和響應(yīng)體過濾函數(shù)的執(zhí)行順序如下所示:

這圖只表示了 head_filter 和 body_filter 之間的執(zhí)行順序,在 header_filter 和 body_filter 處理函數(shù)之間,在 body_filter 處理函數(shù)之間,可能還有其他執(zhí)行代碼。

模塊編譯

Nginx 可以方便的加入第三方的過濾模塊。在過濾模塊的目錄里,首先需要加入 config 文件,文件的內(nèi)容如下:

ngx_addon_name=ngx_http_example_filter_module
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_example_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_example_filter_module.c"

說明把這個(gè)名為 ngx_http_example_filter_module 的過濾模塊加入,ngx_http_example_filter_module.c 是該模塊的源代碼。

注意 HTTP_AUX_FILTER_MODULES 這個(gè)變量與一般的內(nèi)容處理模塊不同。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)