JS#
该模块用于在 njs 中实现处理程序——njs 是 JavaScript 语言的一个子集。
在我们的仓库中,该模块以 动态方式 构建,并作为名为 angie-module-njs 或 angie-pro-module-njs 的独立软件包提供。
备注
还提供了名为 ...-njs-light 的轻量级版本软件包;但是,它不能与常规版本同时使用。
配置示例#
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.
// Inject 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#
设置一个 njs 函数,该函数将在 访问阶段 被调用。可以引用模块函数。
该函数在流会话第一次到达 访问阶段 时被调用一次。该函数使用以下参数调用:
| 流会话 对象 |
在此阶段,可以执行初始化或使用 s.on() 方法为每个传入的数据块注册回调,直到调用以下方法之一: s.done()、s.decline()、s.allow()。一旦调用其中一个方法,流会话处理就会切换到 下一阶段,并且所有当前的 s.on() 回调都会被丢弃。
js_context_reuse#
设置 QuickJS 引擎可重用的 JS 上下文的最大数量。每个上下文用于单个流会话。完成的上下文会被放入可重用上下文池中。如果池已满,则销毁该上下文。
js_engine#
设置用于 njs 脚本的 JavaScript 引擎。njs 参数设置 njs 引擎,这也是默认使用的引擎。qjs 参数设置 QuickJS 引擎。
js_fetch_buffer_size#
设置用于 Fetch API 读取和写入的缓冲区大小。
js_fetch_ciphers#
指定用于 Fetch API HTTPS 连接的启用加密套件。加密套件以 OpenSSL 库理解的格式指定。
加密套件列表取决于安装的 OpenSSL 版本。
可以使用 openssl ciphers 命令查看完整列表。
js_fetch_max_response_buffer_size#
设置使用 Fetch API 接收的响应的最大大小。
js_fetch_protocols#
| |
默认值 |
|
stream, server |
启用用于 Fetch API HTTPS 连接的指定协议。
js_fetch_timeout#
定义 Fetch API 读取和写入的超时时间。超时仅在两次连续的读/写操作之间设置,而不是针对整个响应。如果在此时间内没有数据传输,连接将被关闭。
js_fetch_trusted_certificate#
指定一个包含 PEM 格式受信任 CA 证书的文件,用于验证 Fetch API 的 HTTPS 证书。
js_fetch_verify#
启用或禁用使用 Fetch API 对 HTTPS 服务器证书的验证。
js_fetch_verify_depth#
设置使用 Fetch API 在 HTTPS 服务器证书链中的验证深度。
js_fetch_keepalive#
激活到目标服务器的连接缓存。当该值大于 0 时,为 Fetch API 启用保持活动连接。
connections 参数设置每个工作进程缓存中保留的到目标服务器的空闲保持活动连接的最大数量。当超过此数量时,最近最少使用的连接将被关闭。
示例:
server {
listen 12345;
js_fetch_keepalive 32;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
js_preread main.fetch_handler;
}
js_fetch_keepalive_requests#
设置通过一个与 Fetch API 的保持活动连接可以处理的最大请求数。达到最大请求数后,连接将被关闭。
定期关闭连接对于释放每个连接的内存分配是必要的。因此,使用过高的最大请求数可能导致过度的内存使用,不建议这样做。
js_fetch_keepalive_time#
限制通过一个与 Fetch API 的保持活动连接可以处理请求的最长时间。达到此时间后,连接将在后续请求处理完成后关闭。
js_fetch_keepalive_timeout#
设置与 Fetch API 到目标服务器的空闲保持活动连接保持打开的超时时间。
js_filter#
设置数据过滤器。可以引用模块函数。
过滤器函数在流会话到达 内容阶段 时被调用一次。过滤器函数使用以下参数调用:
| 流会话 对象 |
在此阶段,可以执行初始化或使用 s.on() 方法为每个传入的数据块注册回调。可以使用 s.off() 方法注销回调并停止过滤。
备注
由于 js_filter 处理程序立即返回其结果,因此它仅支持同步操作。因此,不支持异步操作,如 ngx.fetch() 或 setTimeout()。
js_import#
导入一个在 njs 中实现位置和变量处理程序的模块。export_name 用作访问模块函数的命名空间。如果未指定 export_name,则模块名称将用作命名空间。
js_import stream.js;
这里,模块名称 stream 在访问导出时用作命名空间。如果导入的模块导出 foo(),则使用 stream.foo 来访问它。
可以指定多个 js_import 指令。
js_path#
为 njs 模块设置附加路径。
js_periodic#
| |
默认值 | — |
server |
指定定期运行的内容处理程序。该处理程序接收会话对象作为其第一个参数,它还可以访问全局对象,如 ngx。
可选的 interval 参数设置两次连续运行之间的间隔,默认为 5 秒。
可选的 jitter 参数设置位置内容处理程序将被随机延迟的时间,默认情况下没有延迟。
默认情况下,:samp:js_handler 在工作进程 0 上执行。可选的 worker_affinity 参数允许指定应在其中执行位置内容处理程序的特定工作进程。每个工作进程集由允许的工作进程的位掩码表示。all 掩码允许处理程序在所有工作进程中执行。
示例:
example.conf:
location @periodics {
# 在工作进程 0 中以 1 分钟间隔运行
js_periodic main.handler interval=60s;
# 在所有工作进程中以 1 分钟间隔运行
js_periodic main.handler interval=60s worker_affinity=all;
# 在工作进程 1 和 3 中以 1 分钟间隔运行
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://example.com/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
js_preload_object#
在配置时预加载不可变对象。name 用作全局变量的名称,通过该变量可以在 njs 代码中访问该对象。如果未指定 name,则将使用文件名。
js_preload_object map.json;
这里,`map` 在访问预加载对象时用作名称。
可以指定多个 js_preload_object 指令。
js_preread#
设置将在 预读阶段 调用的 njs 函数。可以引用模块函数。
该函数在流会话首次到达 预读阶段 时被调用一次。该函数使用以下参数调用:
| 流会话 对象 |
在此阶段,可以执行初始化或使用 s.on() 方法为每个传入的数据块注册回调,直到调用以下方法之一:s.done()、s.decline()、s.allow()。当调用这些方法之一时,流会话切换到 下一阶段,并且所有当前的 s.on() 回调都将被丢弃。
备注
由于 js_preread 处理程序立即返回其结果,因此它仅支持同步操作。因此,不支持异步操作,如 ngx.fetch() 或 setTimeout()。然而,在 预读阶段 的 s.on() 回调中支持异步操作。
js_set#
为指定的变量设置一个 njs 函数。可以引用模块函数。
当变量在给定请求中首次被引用时,该函数会被调用。确切的时刻取决于引用变量的 阶段。这可以用于执行一些与变量求值无关的逻辑。例如,如果变量仅在 log_format 指令中被引用,其处理程序将不会执行,直到日志阶段。此处理程序可用于在请求被释放之前进行一些清理工作。
从 njs 0.8.6 开始,当提供可选参数 nocache 时,处理程序在每次被引用时都会被调用。由于 rewrite 模块当前的限制,当 nocache 变量被 set 指令引用时,其处理程序应始终返回固定长度的值。
备注
由于 js_set 处理程序会立即返回其结果,因此它仅支持同步操作。因此,不支持异步操作,如 ngx.fetch() 或 setTimeout()。
js_var#
声明一个 可写 变量。值可以包含文本、变量及其组合。
会话对象属性#
每个 stream njs 处理程序接收一个参数,即 stream 会话 对象。