模块 ngx_stream_js_module

示例配置
指令
     js_access
     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 模块用于在 njs 中实现处理程序,njs 是 JavaScript 语言的一个子集。

下载和安装说明 此处 提供。

示例配置

该示例自 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 function | module.function;
默认值
上下文 streamserver

设置一个 njs 函数,该函数将在 access 阶段被调用。自 0.4.0 起,可以引用模块函数。

当流会话首次进入 access 阶段时,该函数将被调用一次。该函数使用以下参数调用

s
流会话 对象

在此阶段,可以执行初始化或使用 s.on() 方法为每个传入的数据块注册回调,直到调用以下方法之一:s.allow()s.decline()s.done()。一旦调用了这些方法中的一个,流会话处理就会切换到 下一个阶段,并且所有当前 s.on() 回调都会被丢弃。

语法 js_fetch_buffer_size size;
默认值
js_fetch_buffer_size 16k;
上下文 streamserver

此指令出现在 0.7.4 版本中。

设置用于使用 Fetch API 进行读写操作的缓冲区的 size

语法 js_fetch_ciphers 密码;
默认值
js_fetch_ciphers HIGH:!aNULL:!MD5;
上下文 streamserver

此指令出现在 0.7.0 版本中。

指定使用 Fetch API 进行 HTTPS 连接的已启用密码。密码以 OpenSSL 库理解的格式指定。

可以使用“openssl ciphers”命令查看完整列表。

语法 js_fetch_max_response_buffer_size 大小;
默认值
js_fetch_max_response_buffer_size 1m;
上下文 streamserver

此指令出现在 0.7.4 版本中。

设置使用 Fetch API 接收的响应的最大大小

语法 js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
默认值
js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;
上下文 streamserver

此指令出现在 0.7.0 版本中。

启用使用 Fetch API 进行 HTTPS 连接的指定协议。

语法 js_fetch_timeout 时间;
默认值
js_fetch_timeout 60s;
上下文 streamserver

此指令出现在 0.7.4 版本中。

定义 Fetch API 的读写超时。超时仅在两次连续的读/写操作之间设置,而不是针对整个响应。如果在此时间内未传输任何数据,则连接将关闭。

语法 js_fetch_trusted_certificate 文件;
默认值
上下文 streamserver

此指令出现在 0.7.0 版本中。

指定一个文件,其中包含 PEM 格式的可信 CA 证书,用于使用 Fetch API 验证 HTTPS 证书。

语法 js_fetch_verify on | off;
默认值
js_fetch_verify on;
上下文 streamserver

此指令出现在 0.7.4 版本中。

启用或禁用使用 Fetch API 验证 HTTPS 服务器证书。

语法 js_fetch_verify_depth 数字;
默认值
js_fetch_verify_depth 100;
上下文 streamserver

此指令出现在 0.7.0 版本中。

使用 Fetch API 设置 HTTPS 服务器证书链中的验证深度。

语法 js_filter 函数 | module.function;
默认值
上下文 streamserver

设置数据过滤器。自 0.4.0 起,可以引用模块函数。当流会话达到 内容 阶段时,将立即调用过滤器函数。

过滤器函数使用以下参数调用

s
流会话 对象

在此阶段,可以使用 s.on() 方法针对每个传入数据块执行初始化或注册回调。可以使用 s.off() 方法注销回调并停止过滤。

由于 js_filter 处理程序立即返回其结果,因此它仅支持同步操作。因此,不支持异步操作,例如 ngx.fetch()setTimeout()

语法 js_import module.js | export_name from module.js;
默认值
上下文 streamserver

此指令出现在 0.4.0 版本中。

导入一个在 njs 中实现位置和变量处理程序的模块。export_name 用作访问模块函数的命名空间。如果未指定 export_name,则模块名称将用作命名空间。

js_import stream.js;

在此处,在访问导出时,模块名称 stream 用作命名空间。如果导入的模块导出 foo(),则使用 stream.foo 引用它。

可以指定多个 js_import 指令。

0.7.7 起,可以在 server 级别指定该指令。

语法 js_include file;
默认值
上下文 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 path;
默认值
上下文 streamserver

此指令出现在版本 0.3.0 中。

为 njs 模块设置一个附加路径。

0.7.7 起,可以在 server 级别指定该指令。

语法 js_periodic function | module.function [interval=time] [jitter=number] [worker_affinity=mask];
默认值
上下文 server

此指令出现在版本 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('http://nginxserver.cn/en/docs/njs/');
    let body = await reply.text();

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

语法 js_preload_object name.json | name from file.json;
默认值
上下文 streamserver

此指令出现在版本 0.7.8 中。

在配置时预加载一个 不可变对象name 用作全局变量的名称,njs 代码可以通过该变量访问该对象。如果未指定 name,则将改用文件名。

js_preload_object map.json;

在此处,在访问预加载对象时,map 用作名称。

可以指定多个 js_preload_object 指令。

语法 js_preread 函数 | 模块.函数;
默认值
上下文 streamserver

设置一个 njs 函数,该函数将在 预读 阶段被调用。自 0.4.0 起,可以引用模块函数。

该函数在流会话首次进入 预读 阶段时被调用一次。该函数使用以下参数被调用

s
流会话 对象

在此阶段,可以执行初始化或使用 s.on() 方法为每个传入数据块注册回调,直到调用以下方法之一:s.allow()s.decline()s.done()。当调用这些方法之一时,流会话切换到 下一个阶段,并且所有当前 s.on() 回调都被丢弃。

由于 js_preread 处理程序立即返回其结果,因此它仅支持同步回调。因此,不支持异步回调,例如 ngx.fetch()setTimeout()。不过,在 预读 阶段的 s.on() 回调中支持异步操作。有关更多信息,请参见 此示例

语法 js_set $变量 函数 | 模块.函数;
默认值
上下文 streamserver

为指定的 变量 设置一个 njs 函数。自 0.4.0 起,可以引用模块函数。

当在给定请求中首次引用变量时,将调用该函数。确切时间取决于引用变量的 阶段。这可用于执行与变量求值无关的一些逻辑。例如,如果仅在 log_format 指令中引用变量,则其处理程序将不会在日志阶段之前执行。此处理程序可用于在请求被释放之前进行一些清理。

由于 js_set 处理程序立即返回其结果,因此它仅支持同步回调。因此,不支持异步回调,例如 ngx.fetch()setTimeout()

0.7.7 起,可以在 server 级别指定该指令。

语法 js_shared_dict_zone zone=名称:大小 [timeout=时间] [type=字符串|数字] [evict];
默认值
上下文 stream

此指令出现在 0.8.0 版本中。

设置共享内存区域的 名称大小,该区域保存键值 字典,在工作进程之间共享。

默认情况下,共享字典使用字符串作为键和值。可选的 type 参数允许将值类型重新定义为数字。

可选的 timeout 参数设置所有共享字典条目从区域中删除的时间。

可选的 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];
默认值
上下文 streamserver

此指令出现在版本 0.5.3 中。

声明一个 可写 变量。该值可以包含文本、变量及其组合。

0.7.7 起,可以在 server 级别指定该指令。

会话对象属性

每个流 njs 处理程序接收一个参数,即流会话 对象