JS#

该模块用于在 njs 中实现处理程序——njs 是 JavaScript 语言的一个子集。

在我们的代码库中,该模块是 动态构建的 并作为一个名为 angie-module-njsangie-pro-module-njs 的独立包提供。

配置示例#

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;
}

// 读取 HTTP 请求行。
// 收集 'req' 中的字节,直到
// 请求行被读取。
// 将 HTTP 头注入客户端请求

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#

语法

js_access function | module.function;

默认值

上下文

stream, server

设置将在 访问阶段 调用的 njs 函数。可以引用模块函数。

当流会话首次达到 访问阶段 时,该函数会被调用一次。该函数使用以下参数调用:

s

stream session 对象

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

js_fetch_buffer_size#

语法

js_fetch_buffer_size size;

默认值

js_fetch_buffer_size 16k;

上下文

stream, server

设置用于读取和写入 Fetch API 的缓冲区大小。

js_fetch_ciphers#

语法

js_fetch_ciphers ciphers;

默认值

js_fetch_ciphers HIGH:!aNULL:!MD5;

上下文

stream, server

指定 Fetch API 的 HTTPS 连接中启用的加密套件。这些加密套件以 OpenSSL 库理解的格式指定。

可使用 "openssl ciphers" 命令查看完整列表。

js_fetch_max_response_buffer_size#

语法

js_fetch_max_response_buffer_size size;

默认值

js_fetch_max_response_buffer_size 1m;

上下文

stream, server

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

js_fetch_protocols#

语法

js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];

默认值

js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;

上下文

stream, server

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

js_fetch_timeout#

语法

js_fetch_timeout time;

默认值

js_fetch_timeout 60s;

上下文

stream, server

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

js_fetch_trusted_certificate#

语法

js_fetch_trusted_certificate file;

默认值

上下文

stream, server

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

js_fetch_verify#

语法

js_fetch_verify on | off;

默认值

js_fetch_verify on;

上下文

stream, server

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

js_fetch_verify_depth#

语法

js_fetch_verify_depth number;

默认值

js_fetch_verify_depth 100;

上下文

stream, server

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

js_filter#

语法

js_filter function | module.function;

默认值

上下文

stream, server

设置数据过滤器。可以引用模块函数。

当流会话达到 内容阶段 时,过滤器函数会被调用一次。过滤器函数使用以下参数调用:

s

stream session 对象

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

备注

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

js_import#

语法

js_import module.js | export_name from module.js;

默认值

上下文

stream, server

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

js_import stream.js;

在此,模块名称 stream 被用作

可以指定多个 js_import 指令。

js_path#

语法

js_path path;

默认值

上下文

stream, server

设置 njs 模块的附加路径。

js_preload_object#

语法

js_preload_object name.json | name from file.json;

默认值

上下文

stream, server

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

js_preload_object map.json;

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

可以指定多个 js_preload_object 指令。

js_preread#

语法

js_preread function | module.function;

默认值

上下文

stream, server

设置将在 预读取阶段 调用的 njs 函数。可以引用模块函数。

当流会话首次达到 预读取阶段 时,该函数会被调用一次。该函数使用以下参数调用:

s

stream session 对象

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

备注

因为 js_preread 处理器会立即返回其结果,所以它仅支持同步回调。因此,不支持像 ngx.fetch()setTimeout() 这样的异步回调。不过,在 预读阶段s.on() 回调中支持异步操作。

js_set#

语法

js_set $variable function | module.function;

默认值

上下文

stream, server

为指定变量设置 njs 函数。可以引用模块函数。

当第一次引用给定请求的变量时调用该函数。具体时机取决于引用变量的 阶段。这可以用于执行一些与变量评估无关的逻辑。例如,如果变量仅在 log_format 指令中引用,其处理器将在日志阶段之前不会被执行。这个处理器可以用于在请求释放之前进行一些清理。

备注

因为 js_set 处理器会立即返回其结果,所以它仅支持同步回调。因此,不支持像 ngx.fetch()setTimeout() 这样的异步回调。

js_shared_dict_zone#

语法

js_shared_dict_zone zone=name:size [timeout=time] [type=string | number] [evict];

默认值

上下文

stream

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

type

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

timeout

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

evict

可选参数,当区域存储耗尽时,移除最旧的键值对

示例:

example.conf:
    # 创建一个1Mb的字典,值为字符串,
    # 在60秒不活动后移除键值对:
    js_shared_dict_zone zone=foo:1M timeout=60s;

    # 创建一个512Kb的字典,值为字符串,
    # 当区域耗尽时强制移除最旧的键值对:
    js_shared_dict_zone zone=bar:512K timeout=30s evict;

    # 创建一个32Kb的永久字典,值为数字:
    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 delete(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#

语法

js_var $variable [value];

默认值

上下文

stream, server

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

会话对象属性#

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