モジュール ngx_stream_js_module

設定例
ディレクティブ
     js_access
     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_filter
     js_import
     js_include
     js_path
     js_periodic
     js_preload_object
     js_preread
     js_set
     js_shared_dict_zone
     js_var
セッションオブジェクトのプロパティ

ngx_stream_js_moduleモジュールは、JavaScript言語のサブセットであるnjsでハンドラを実装するために使用されます。

ダウンロードとインストールの手順はこちらにあります。

設定例

この例は0.4.0以降で動作します。

stream {
    js_import stream.js;

    js_set $bar stream.bar;
    js_set $req_line stream.req_line;

    server {
        listen 12345;

        js_preread stream.preread;
        return     $req_line;
    }

    server {
        listen 12346;

        js_access  stream.access;
        proxy_pass 127.0.0.1:8000;
        js_filter  stream.header_inject;
    }
}

http {
    server {
        listen 8000;
        location / {
            return 200 $http_foo\n;
        }
    }
}

stream.jsファイル

var line = '';

function bar(s) {
    var v = s.variables;
    s.log("hello from bar() handler!");
    return "bar-var" + v.remote_port + "; pid=" + v.pid;
}

function preread(s) {
    s.on('upload', function (data, flags) {
        var n = data.indexOf('\n');
        if (n != -1) {
            line = data.substr(0, n);
            s.done();
        }
    });
}

function req_line(s) {
    return line;
}

// Read HTTP request line.
// Collect bytes in 'req' until
// request line is read.
// Injects HTTP header into a client's request

var my_header =  'Foo: foo';
function header_inject(s) {
    var req = '';
    s.on('upload', function(data, flags) {
        req += data;
        var n = req.search('\n');
        if (n != -1) {
            var rest = req.substr(n + 1);
            req = req.substr(0, n + 1);
            s.send(req + my_header + '\r\n' + rest, flags);
            s.off('upload');
        }
    });
}

function access(s) {
    if (s.remoteAddress.match('^192.*')) {
        s.deny();
        return;
    }

    s.allow();
}

export default {bar, preread, req_line, header_inject, access};

ディレクティブ

構文 js_access 関数 | module.関数;
デフォルト
コンテキスト stream, server

アクセスフェーズで呼び出されるnjs関数を設定します。0.4.0以降、モジュール関数を参照できます。

この関数は、ストリームセッションが初めてアクセスフェーズに到達した時点で1回呼び出されます。関数は、以下の引数を使用して呼び出されます。

s
ストリームセッションオブジェクト

このフェーズでは、初期化を実行したり、s.allow()s.decline()s.done()のいずれかのメソッドが呼び出されるまで、受信データチャンクごとにs.on()メソッドを使用してコールバックを登録できます。これらのメソッドのいずれかが呼び出されるとすぐに、ストリームセッション処理は次のフェーズに切り替わり、現在のs.on()コールバックはすべて削除されます。

構文 js_context_reuse 数値;
デフォルト
js_context_reuse 128;
コンテキスト stream, server

このディレクティブはバージョン0.8.6で追加されました。

QuickJSエンジンで再利用されるJSコンテキストの最大数を設定します。各コンテキストは単一のストリームセッションで使用されます。終了したコンテキストは、再利用可能なコンテキストのプールに入れられます。プールがいっぱいになっている場合、コンテキストは破棄されます。

構文 js_engine njs | qjs;
デフォルト
js_engine njs;
コンテキスト stream, server

このディレクティブはバージョン0.8.6で追加されました。

njsスクリプトで使用されるJavaScriptエンジンを設定します。njsパラメータは、デフォルトでも使用されるnjsエンジンを設定します。qjsパラメータはQuickJSエンジンを設定します。

構文 js_fetch_buffer_size サイズ;
デフォルト
js_fetch_buffer_size 16k;
コンテキスト stream, server

このディレクティブはバージョン0.7.4で追加されました。

Fetch APIで読み書きに使用されるバッファのサイズを設定します。

構文 js_fetch_ciphers 暗号;
デフォルト
js_fetch_ciphers HIGH:!aNULL:!MD5;
コンテキスト stream, server

このディレクティブはバージョン0.7.0で追加されました。

Fetch APIを使用したHTTPS接続で有効にする暗号を指定します。暗号は、OpenSSLライブラリで認識される形式で指定します。

完全なリストは、「openssl ciphers」コマンドを使用して表示できます。

構文 js_fetch_max_response_buffer_size サイズ;
デフォルト
js_fetch_max_response_buffer_size 1m;
コンテキスト stream, server

このディレクティブはバージョン0.7.4で追加されました。

Fetch APIで受信した応答の最大サイズを設定します。

構文 js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
デフォルト
js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;
コンテキスト stream, server

このディレクティブはバージョン0.7.0で追加されました。

Fetch APIを使用したHTTPS接続で指定されたプロトコルを有効にします。

構文 js_fetch_timeout 時間;
デフォルト
js_fetch_timeout 60s;
コンテキスト stream, server

このディレクティブはバージョン0.7.4で追加されました。

Fetch APIの読み書きのタイムアウトを定義します。タイムアウトは、2つの連続した読み書き操作の間のみに設定され、応答全体には設定されません。この時間内にデータが送信されない場合、接続は閉じられます。

構文 js_fetch_trusted_certificate ファイル;
デフォルト
コンテキスト stream, server

このディレクティブはバージョン0.7.0で追加されました。

Fetch APIでHTTPS証明書を検証するために使用される、PEM形式の信頼できるCA証明書を含むファイルを指定します。

構文 js_fetch_verify on | off;
デフォルト
js_fetch_verify on;
コンテキスト stream, server

このディレクティブはバージョン0.7.4で追加されました。

Fetch APIでHTTPSサーバー証明書の検証を有効または無効にします。

構文 js_fetch_verify_depth 数値;
デフォルト
js_fetch_verify_depth 100;
コンテキスト stream, server

このディレクティブはバージョン0.7.0で追加されました。

Fetch APIでHTTPSサーバー証明書チェーンの検証深度を設定します。

構文 js_filter 関数 | module.関数;
デフォルト
コンテキスト stream, server

データフィルタを設定します。0.4.0以降、モジュール関数を参照できます。フィルタ関数は、ストリームセッションがコンテンツフェーズに到達した時点で1回呼び出されます。

フィルタ関数は、以下の引数を使用して呼び出されます。

s
ストリームセッションオブジェクト

このフェーズでは、初期化を実行したり、受信データチャンクごとにs.on()メソッドを使用してコールバックを登録できます。s.off()メソッドを使用してコールバックの登録を解除し、フィルタリングを停止できます。

js_filterハンドラは結果をすぐに返すため、同期操作のみをサポートしています。そのため、ngx.fetch()setTimeout()などの非同期操作はサポートされていません。

構文 js_import module.js | export_name from module.js;
デフォルト
コンテキスト stream, server

このディレクティブはバージョン0.4.0で追加されました。

ロケーションと変数ハンドラを実装するモジュールをインポートします。export_nameは、モジュール関数にアクセスするための名前空間として使用されます。export_nameを指定しない場合、モジュール名が名前空間として使用されます。

js_import stream.js;

ここでは、エクスポートにアクセスする際にstreamというモジュール名が名前空間として使用されます。インポートされたモジュールがfoo()をエクスポートする場合、stream.fooを使用して参照します。

複数のjs_importディレクティブを指定できます。

0.7.7以降、このディレクティブはserverレベルで指定できます。

構文 js_include ファイル;
デフォルト
コンテキスト stream

njsでサーバーと変数ハンドラを実装するファイルを指定します。

nginx.conf:
js_include stream.js;
js_set     $js_addr address;
server {
    listen 127.0.0.1:12345;
    return $js_addr;
}

stream.js:
function address(s) {
    return s.remoteAddress;
}

このディレクティブはバージョン0.4.0で非推奨となり、バージョン0.7.1で削除されました。js_importディレクティブを使用してください。

構文 js_path パス;
デフォルト
コンテキスト stream, server

このディレクティブはバージョン0.3.0で追加されました。

njsモジュールの追加パスを設定します。

0.7.7以降、このディレクティブはserverレベルで指定できます。

構文 js_periodic 関数 | module.関数 [interval=時間] [jitter=数値] [worker_affinity=マスク];
デフォルト
コンテキスト server

このディレクティブはバージョン0.8.1で追加されました。

定期的な間隔で実行されるコンテンツハンドラを指定します。ハンドラは、最初の引数としてセッションオブジェクトを受信し、ngxなどのグローバルオブジェクトにもアクセスできます。

オプションのintervalパラメータは、2回連続した実行の間隔を設定します。デフォルトは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.dokyumento.jp/en/docs/njs/');
    let body = await reply.text();

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

構文 js_preload_object name.json | name from file.json;
デフォルト
コンテキスト stream, server

このディレクティブはバージョン0.7.8で追加されました。

設定時に不変オブジェクトをプリロードします。nameは、njsコードでオブジェクトが使用できるグローバル変数の名前として使用されます。nameを指定しない場合、ファイル名が代わりに使用されます。

js_preload_object map.json;

ここでは、プリロードされたオブジェクトにアクセスする際にmapが名前として使用されます。

複数のjs_preload_objectディレクティブを指定できます。

構文 js_preread 関数 | module.関数;
デフォルト
コンテキスト stream, server

prereadフェーズで呼び出されるnjs関数を設定します。0.4.0以降、モジュール関数を参照できます。

この関数は、ストリームセッションが初めてprereadフェーズに到達した時点で1回呼び出されます。関数は、以下の引数を使用して呼び出されます。

s
ストリームセッションオブジェクト

このフェーズでは、初期化を実行したり、s.allow()s.decline()s.done()のいずれかのメソッドが呼び出されるまで、受信データチャンクごとにs.on()メソッドを使用してコールバックを登録できます。これらのメソッドのいずれかが呼び出されると、ストリームセッションは次のフェーズに切り替わり、現在のs.on()コールバックはすべて削除されます。

js_prereadハンドラは結果をすぐに返すため、同期コールバックのみをサポートしています。そのため、ngx.fetch()setTimeout()などの非同期コールバックはサポートされていません。ただし、prereadフェーズでは、s.on()コールバックで非同期操作がサポートされています。詳細についてはこの例を参照してください。

構文 js_set $変数 関数 | module.関数 [nocache];
デフォルト
コンテキスト stream, server

指定された変数に対してnjs関数を設定します。0.4.0以降、モジュール関数を参照できます。

この関数は、特定のリクエストに対して変数が初めて参照されたときに呼び出されます。正確なタイミングは、変数が参照されるフェーズによって異なります。これは、変数の評価とは関係のないロジックを実行するために使用できます。たとえば、変数がlog_formatディレクティブでのみ参照される場合、そのハンドラはログフェーズまで実行されません。このハンドラを使用して、リクエストが解放される直前にクリーンアップを実行できます。

0.8.6以降、オプションの引数nocacheが指定されている場合、ハンドラは参照されるたびに呼び出されます。rewriteモジュールの現在の制限により、setディレクティブでnocache変数が参照される場合、そのハンドラは常に固定長の値を返す必要があります。

js_setハンドラは結果をすぐに返すため、同期コールバックのみをサポートしています。そのため、ngx.fetch()setTimeout()などの非同期コールバックはサポートされていません。

0.7.7以降、このディレクティブはserverレベルで指定できます。

構文 js_shared_dict_zone zone=名前:サイズ [timeout=時間] [type=string|number] [evict];
デフォルト
コンテキスト stream

このディレクティブはバージョン0.8.0で追加されました。

ワーカープロセス間で共有されるキーバリューディクショナリを保持する共有メモリゾーンの名前サイズを設定します。

デフォルトでは、共有ディクショナリはキーとして文字列、値として文字列を使用します。オプションの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 $変数 [];
デフォルト
コンテキスト stream, server

このディレクティブは、バージョン0.5.3から導入されました。

書き込み可能な変数を宣言します。値には、テキスト、変数、およびそれらを組み合わせたものを指定できます。

0.7.7以降、このディレクティブはserverレベルで指定できます。

セッションオブジェクトのプロパティ

各ストリームnjsハンドラは、ストリームセッションオブジェクトを1つの引数として受け取ります。