ngx_http_js_module 模組

範例組態
指令
     js_body_filter
     js_content
     js_context_reuse
     js_engine
     js_fetch_buffer_size
     js_fetch_ciphers
     js_fetch_max_response_buffer_size
     js_fetch_protocols
     js_fetch_timeout
     js_fetch_trusted_certificate
     js_fetch_verify
     js_fetch_verify_depth
     js_header_filter
     js_import
     js_include
     js_path
     js_periodic
     js_preload_object
     js_set
     js_shared_dict_zone
     js_var
請求參數

ngx_http_js_module 模組用於在 njs (JavaScript 語言的子集)中實作位置和變數處理程式。

下載和安裝說明請見此處

範例組態

此範例適用於 0.4.0 或更新版本。

http {
    js_import http.js;

    js_set $foo     http.foo;
    js_set $summary http.summary;
    js_set $hash    http.hash;

    resolver 10.0.0.1;

    server {
        listen 8000;

        location / {
            add_header X-Foo $foo;
            js_content http.baz;
        }

        location = /summary {
            return 200 $summary;
        }

        location = /hello {
            js_content http.hello;
        }

        # since 0.7.0
        location = /fetch {
            js_content                   http.fetch;
            js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
        }

        # since 0.7.0
        location = /crypto {
            add_header Hash $hash;
            return     200;
        }
    }
}

http.js 檔案

function foo(r) {
    r.log("hello from foo() handler");
    return "foo";
}

function summary(r) {
    var a, s, h;

    s = "JS summary\n\n";

    s += "Method: " + r.method + "\n";
    s += "HTTP version: " + r.httpVersion + "\n";
    s += "Host: " + r.headersIn.host + "\n";
    s += "Remote Address: " + r.remoteAddress + "\n";
    s += "URI: " + r.uri + "\n";

    s += "Headers:\n";
    for (h in r.headersIn) {
        s += "  header '" + h + "' is '" + r.headersIn[h] + "'\n";
    }

    s += "Args:\n";
    for (a in r.args) {
        s += "  arg '" + a + "' is '" + r.args[a] + "'\n";
    }

    return s;
}

function baz(r) {
    r.status = 200;
    r.headersOut.foo = 1234;
    r.headersOut['Content-Type'] = "text/plain; charset=utf-8";
    r.headersOut['Content-Length'] = 15;
    r.sendHeader();
    r.send("nginx");
    r.send("java");
    r.send("script");

    r.finish();
}

function hello(r) {
    r.return(200, "Hello world!");
}

// since 0.7.0
async function fetch(r) {
    let results = await Promise.all([ngx.fetch('https://nginx.dev.org.tw/'),
                                     ngx.fetch('https://nginx.dev.org.tw/en/')]);

    r.return(200, JSON.stringify(results, undefined, 4));
}

// since 0.7.0
async function hash(r) {
    let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
    r.setReturnValue(Buffer.from(hash).toString('hex'));
}

export default {foo, summary, baz, hello, fetch, hash};

指令

語法 js_body_filter function | module.function [buffer_type=string | buffer];
預設
內容 locationif in locationlimit_except

此指令出現於 0.5.2 版。

將 njs 函式設定為回應主體篩選器。篩選函式會針對回應主體的每個資料區塊呼叫,並具有下列引數

r
HTTP 請求物件
data
傳入的資料區塊,可能是字串或緩衝區,取決於 buffer_type 值,預設為字串。自 0.8.5 起,預設情況下,data 值會隱式轉換為有效的 UTF-8 字串。對於二進位資料,應將 buffer_type 值設定為 buffer
flags
具有下列屬性的物件
last
布林值,如果資料是最後一個緩衝區,則為 true。

篩選函式可以透過呼叫 r.sendBuffer() 將其修改後的輸入資料區塊版本傳遞給下一個主體篩選器。例如,要轉換回應主體中的所有小寫字母

function filter(r, data, flags) {
    r.sendBuffer(data.toLowerCase(), flags);
}

若要停止篩選(後續的資料區塊將在不呼叫 js_body_filter 的情況下傳遞給用戶端),可以使用 r.done()

如果篩選函式變更了回應主體的長度,則必須在 js_header_filter 中清除「Content-Length」回應標頭(如果有的話),以強制執行分塊傳輸編碼。

由於 js_body_filter 處理程式會立即傳回其結果,因此僅支援同步操作。因此,不支援 r.subrequest()setTimeout() 等非同步操作。

0.7.7 起,可以在 if 區塊內指定此指令。

語法 js_content function | module.function;
預設
內容 locationif in locationlimit_except

將 njs 函式設定為位置內容處理程式。自 0.4.0 起,可以參考模組函式。

0.7.7 起,可以在 if 區塊內指定此指令。

語法 js_context_reuse number;
預設
js_context_reuse 128;
內容 httpserverlocation

此指令出現於 0.8.6 版。

設定 QuickJS 引擎可重複使用的 JS 內容最大數量。每個內容用於單個請求。完成的內容會放入可重複使用內容的集區中。如果集區已滿,則會銷毀該內容。

語法 js_engine njs | qjs;
預設
js_engine njs;
內容 httpserverlocation

此指令出現於 0.8.6 版。

設定用於 njs 腳本的JavaScript 引擎njs 參數設定 njs 引擎,預設也會使用。qjs 參數設定 QuickJS 引擎。

語法 js_fetch_buffer_size size;
預設
js_fetch_buffer_size 16k;
內容 httpserverlocation

此指令出現於 0.7.4 版。

設定使用 Fetch API 讀取和寫入時所使用的緩衝區的 size

語法 js_fetch_ciphers ciphers;
預設
js_fetch_ciphers HIGH:!aNULL:!MD5;
內容 httpserverlocation

此指令出現於 0.7.0 版。

指定透過 Fetch API 發出 HTTPS 請求時所啟用的密碼。密碼以 OpenSSL 程式庫理解的格式指定。

可以使用「openssl ciphers」命令檢視完整清單。

語法 js_fetch_max_response_buffer_size size;
預設
js_fetch_max_response_buffer_size 1m;
內容 httpserverlocation

此指令出現於 0.7.4 版。

設定透過 Fetch API 接收的回應的最大 size

語法 js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
預設
js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;
內容 httpserverlocation

此指令出現於 0.7.0 版。

啟用透過 Fetch API 發出 HTTPS 請求時所指定的通訊協定。

語法 js_fetch_timeout time;
預設
js_fetch_timeout 60s;
內容 httpserverlocation

此指令出現於 0.7.4 版。

定義透過 Fetch API 讀取和寫入的逾時。逾時僅在兩個連續的讀取/寫入操作之間設定,而不是針對整個回應。如果在此時間內沒有傳輸任何資料,則會關閉連線。

語法 js_fetch_trusted_certificate file;
預設
內容 httpserverlocation

此指令出現於 0.7.0 版。

指定以 PEM 格式包含信任 CA 憑證的 file,用於透過 Fetch API 驗證 HTTPS 憑證。

語法 js_fetch_verify on | off;
預設
js_fetch_verify on;
內容 httpserverlocation

此指令出現於 0.7.4 版。

啟用或停用透過 Fetch API 驗證 HTTPS 伺服器憑證。

語法 js_fetch_verify_depth number;
預設
js_fetch_verify_depth 100;
內容 httpserverlocation

此指令出現於 0.7.0 版。

設定透過 Fetch API 驗證 HTTPS 伺服器憑證鏈中的深度。

語法 js_header_filter function | module.function;
預設
內容 locationif in locationlimit_except

此指令出現於 0.5.1 版。

將 njs 函式設定為回應標頭篩選器。此指令允許變更回應標頭的任意標頭欄位。

由於 js_header_filter 處理程式會立即傳回其結果,因此僅支援同步操作。因此,不支援 r.subrequest()setTimeout() 等非同步操作。

0.7.7 起,可以在 if 區塊內指定此指令。

語法 js_import module.js | export_name from module.js;
預設
內容 httpserverlocation

此指令出現於 0.4.0 版。

匯入在 njs 中實作位置和變數處理程式的模組。export_name 用作存取模組函式的命名空間。如果未指定 export_name,則模組名稱將用作命名空間。

js_import http.js;

在此範例中,模組名稱 http 用作存取匯出項目的命名空間。如果匯入的模組匯出 foo(),則使用 http.foo 來參考它。

可以指定數個 js_import 指令。

0.7.7 起,可以在 serverlocation 層級指定此指令。

語法 js_include file;
預設
內容 http

指定實作 njs 中的位置和變數處理程式的檔案

nginx.conf:
js_include http.js;
location   /version {
    js_content version;
}

http.js:
function version(r) {
    r.return(200, njs.version);
}

此指令在 0.4.0 版中已過時,並在 0.7.1 版中移除。應改用 js_import 指令。

語法 js_path path;
預設
內容 httpserverlocation

此指令出現於 0.3.0 版。

設定 njs 模組的其他路徑。

0.7.7 起,可以在 serverlocation 層級指定此指令。

語法 js_periodic function | module.function [interval=time] [jitter=number] [worker_affinity=mask];
預設
內容 location

此指令出現於 0.8.1 版。

指定以固定間隔執行的內容處理程式。處理程式會接收 工作階段物件 作為其第一個引數,它也可以存取 ngx 等全域物件。

選用的 interval 參數設定兩個連續執行之間的間隔,預設為 5 秒。

選用的 jitter 參數設定位置內容處理程式將隨機延遲的時間,預設情況下,沒有延遲。

預設情況下,js_handler 在工作處理程序 0 上執行。選用的 worker_affinity 參數允許指定應執行位置內容處理程式的特定工作處理程序。每個工作處理程序集由允許的工作處理程序位元遮罩表示。all 遮罩允許在所有工作處理程序中執行處理程式。

範例

example.conf:

location @periodics {
    # to be run at 1 minute intervals in worker process 0
    js_periodic main.handler interval=60s;

    # to be run at 1 minute intervals in all worker processes
    js_periodic main.handler interval=60s worker_affinity=all;

    # to be run at 1 minute intervals in worker processes 1 and 3
    js_periodic main.handler interval=60s worker_affinity=0101;

    resolver 10.0.0.1;
    js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}

example.js:

async function handler(s) {
    let reply = await ngx.fetch('https://nginx.dev.org.tw/en/docs/njs/');
    let body = await reply.text();

    ngx.log(ngx.INFO, body);
}

語法 js_preload_object name.json | name from file.json;
預設
內容 httpserverlocation

此指令出現於 0.7.8 版。

在設定時預載入不可變物件name 用作全域變數的名稱,透過該變數可以在 njs 程式碼中使用該物件。如果未指定 name,則會改用檔案名稱。

js_preload_object map.json;

在此範例中,map 用作存取預載入物件時的名稱。

可以指定數個 js_preload_object 指令。

語法 js_set $variable function | module.function [nocache];
預設
內容 httpserverlocation

為指定的 variable 設定 njs function。自 0.4.0 起,可以參考模組函式。

當在給定的請求中第一次參考變數時,會呼叫該函式。確切的時間取決於參考變數的階段。這可以用於執行一些與變數評估無關的邏輯。例如,如果僅在 log_format 指令中參考該變數,則其處理程式將不會執行,直到記錄階段為止。此處理程式可用於在釋放請求之前執行一些清除。

0.8.6 起,如果指定了選用引數 nocache,則每次參考時都會呼叫該處理程式。由於 rewrite 模組目前的限制,當 set 指令參考 nocache 變數時,其處理程式應始終傳回固定長度的值。

由於 js_set 處理程式會立即傳回其結果,因此僅支援同步操作。因此,不支援 r.subrequest()setTimeout() 等非同步操作。

0.7.7 起,可以在 serverlocation 層級指定此指令。

語法 js_shared_dict_zone zone=name:size [timeout=time] [type=string|number] [evict];
預設
內容 http

此指令出現於 0.8.0 版。

設定共用記憶體區域的 namesize,該區域會保留工作處理程序之間共用的鍵值字典

預設情況下,共用字典使用字串作為鍵和值。選用的 type 參數允許將值類型重新定義為數字。

選用的 timeout 參數設定以毫秒為單位的時間,在此時間之後,所有共用字典項目都會從區域中移除。如果某些項目需要不同的移除時間,可以使用 addincrset 方法的 timeout 引數設定 (0.8.5)。

選用的 evict 參數會在區域儲存耗盡時移除最舊的鍵值對。

範例

example.conf:
    # Creates a 1Mb dictionary with string values,
    # removes key-value pairs after 60 seconds of inactivity:
    js_shared_dict_zone zone=foo:1M timeout=60s;

    # Creates a 512Kb dictionary with string values,
    # forcibly removes oldest key-value pairs when the zone is exhausted:
    js_shared_dict_zone zone=bar:512K timeout=30s evict;

    # Creates a 32Kb permanent dictionary with number values:
    js_shared_dict_zone zone=num:32k type=number;

example.js:
    function get(r) {
        r.return(200, ngx.shared.foo.get(r.args.key));
    }

    function set(r) {
        r.return(200, ngx.shared.foo.set(r.args.key, r.args.value));
    }

    function del(r) {
        r.return(200, ngx.shared.bar.delete(r.args.key));
    }

    function increment(r) {
        r.return(200, ngx.shared.num.incr(r.args.key, 2));
    }

語法 js_var $variable [value];
預設
內容 httpserverlocation

此指令出現於 0.5.3 版。

宣告一個可寫入的變數。該值可以包含文字、變數及其組合。與使用 set 指令建立的變數不同,此變數在重導向後不會被覆寫。

0.7.7 起,可以在 serverlocation 層級指定此指令。

請求參數

每個 HTTP njs 處理器都會接收一個參數,即一個請求物件