模块 ngx_http_js_module
ngx_http_js_module 模块用于在 njs(JavaScript 语言的一个子集)中实现 location 和变量处理程序。
下载和安装说明可在此处获取:此处。
配置示例
该示例自 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.ac.cn/'),
ngx.fetch('https://nginx.ac.cn/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 |
|---|---|
| 默认值 | — |
| 上下文 |
location, if in location, limit_except |
该指令出现在 0.5.2 版本。
将 njs 函数设置为响应体过滤器。过滤器函数会为响应体的每个数据块调用,参数如下:
r- HTTP 请求对象
data- 传入的数据块,可能是字符串或 Buffer,取决于
buffer_type的值,默认为字符串。自 0.8.5 版本起,data的值默认隐式转换为有效的 UTF-8 字符串。对于二进制数据,应将buffer_type值设置为buffer。 flags- 一个具有以下属性的对象
last- 一个布尔值,如果 data 是最后一个 buffer,则为 true。
过滤器函数可以通过调用 r.sendBuffer() 将输入数据块的修改版本传递给下一个 body 过滤器。例如,转换响应体中的所有小写字母:
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 |
|---|---|
| 默认值 | — |
| 上下文 |
location, if in location, limit_except |
将 njs 函数设置为 location 内容处理程序。自 0.4.0 版本起,可以引用模块函数。
自 0.7.7 版本起,该指令可以在 if 块内指定。
| 语法 |
js_context_reuse |
|---|---|
| 默认值 |
js_context_reuse 128; |
| 上下文 |
http, server, location |
该指令出现在 0.8.6 版本。
设置 QuickJS 引擎可重用的最大 JS 上下文数量。每个上下文用于处理单个请求。完成的上下文会被放入可重用上下文池中。如果池满,上下文将被销毁。
| 语法 |
js_engine |
|---|---|
| 默认值 |
js_engine njs; |
| 上下文 |
http, server, location |
该指令出现在 0.8.6 版本。
设置用于 njs 脚本的 JavaScript 引擎。参数 njs 设置 njs 引擎,该引擎也是默认使用的。参数 qjs 设置 QuickJS 引擎。
| 语法 |
js_fetch_buffer_size |
|---|---|
| 默认值 |
js_fetch_buffer_size 16k; |
| 上下文 |
http, server, location |
该指令出现在 0.7.4 版本。
设置使用 Fetch API 进行读写时使用的缓冲区 size。
| 语法 |
js_fetch_ciphers |
|---|---|
| 默认值 |
js_fetch_ciphers HIGH:!aNULL:!MD5; |
| 上下文 |
http, server, location |
该指令出现在 0.7.0 版本。
指定使用 Fetch API 进行 HTTPS 请求时启用的密码套件。密码套件格式由 OpenSSL 库识别。
完整列表可以使用 “openssl ciphers” 命令查看。
| 语法 |
js_fetch_max_response_buffer_size |
|---|---|
| 默认值 |
js_fetch_max_response_buffer_size 1m; |
| 上下文 |
http, server, location |
该指令出现在 0.7.4 版本。
设置使用 Fetch API 接收的最大响应 size。
| 语法 |
js_fetch_protocols [ |
|---|---|
| 默认值 |
js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2; |
| 上下文 |
http, server, location |
该指令出现在 0.7.0 版本。
为使用 Fetch API 进行的 HTTPS 请求启用指定的协议。
| 语法 |
js_fetch_timeout |
|---|---|
| 默认值 |
js_fetch_timeout 60s; |
| 上下文 |
http, server, location |
该指令出现在 0.7.4 版本。
定义使用 Fetch API 进行读写的超时时间。该超时仅应用于连续两次读/写操作之间,而非整个响应过程。如果在此时间内没有数据传输,连接将关闭。
| 语法 |
js_fetch_trusted_certificate |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
该指令出现在 0.7.0 版本。
指定一个 file,其中包含 PEM 格式的受信任 CA 证书,用于使用 Fetch API 验证 HTTPS 证书。
| 语法 |
js_fetch_verify |
|---|---|
| 默认值 |
js_fetch_verify on; |
| 上下文 |
http, server, location |
该指令出现在 0.7.4 版本。
启用或禁用使用 Fetch API 对 HTTPS 服务器证书的验证。
| 语法 |
js_fetch_verify_depth |
|---|---|
| 默认值 |
js_fetch_verify_depth 100; |
| 上下文 |
http, server, location |
该指令出现在 0.7.0 版本。
设置使用 Fetch API 对 HTTPS 服务器证书链进行验证的深度。
| 语法 |
js_header_filter |
|---|---|
| 默认值 | — |
| 上下文 |
location, if in location, limit_except |
该指令出现在 0.5.1 版本。
将 njs 函数设置为响应头过滤器。该指令允许修改响应头中的任意头字段。
由于 js_header_filter 处理程序立即返回结果,它仅支持同步操作。因此,不支持异步操作,例如 r.subrequest() 或 setTimeout()。
自 0.7.7 版本起,该指令可以在 if 块内指定。
| 语法 |
js_import |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
该指令出现在 0.4.0 版本。
导入一个在 njs 中实现 location 和变量处理程序的模块。export_name 用作访问模块函数的命名空间。如果未指定 export_name,则使用模块名作为命名空间。
js_import http.js;
在这里,访问导出时使用模块名 http 作为命名空间。如果导入的模块导出了 foo() 函数,则使用 http.foo 来引用它。
可以指定多个 js_import 指令。
自 0.7.7 版本起,该指令可以在server和location级别指定。
| 语法 |
js_include |
|---|---|
| 默认值 | — |
| 上下文 |
http |
指定一个在 njs 中实现 location 和变量处理程序的文件
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 |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
该指令出现在 0.3.0 版本。
为 njs 模块设置一个附加路径。
自 0.7.7 版本起,该指令可以在server和location级别指定。
| 语法 |
js_periodic |
|---|---|
| 默认值 | — |
| 上下文 |
location |
该指令出现在 0.8.1 版本。
指定一个内容处理程序,以固定间隔运行。处理程序接收一个 session 对象作为其第一个参数,并且可以访问全局对象,例如 ngx。
可选参数 interval 设置两次连续运行之间的间隔,默认为 5 秒。
可选参数 jitter 设置 location 内容处理程序将被随机延迟的时间范围,默认没有延迟。
默认情况下,js_handler 在 worker 进程 0 上执行。可选参数 worker_affinity 允许指定应执行 location 内容处理程序的特定 worker 进程。每个 worker 进程集由允许的 worker 进程的位掩码表示。all 掩码允许处理程序在所有 worker 进程中执行。
示例
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.ac.cn/en/docs/njs/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
| 语法 |
js_preload_object |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
该指令出现在 0.7.8 版本。
在配置时预加载一个 不可变对象。name 用作全局变量名,njs 代码可以通过该变量名访问该对象。如果未指定 name,则使用文件名代替。
js_preload_object map.json;
在这里,访问预加载对象时,使用 map 作为名称。
可以指定多个 js_preload_object 指令。
| 语法 |
js_set |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
为指定的 variable 设置一个 njs function。自 0.4.0 版本起,可以引用模块函数。
在给定请求首次引用变量时调用此函数。确切的调用时机取决于变量在 哪个阶段被引用。这可用于执行一些与变量评估无关的逻辑。例如,如果变量仅在 log_format 指令中被引用,其处理程序直到日志阶段才会执行。此处理程序可用于在请求释放之前进行一些清理工作。
自 0.8.6 版本起,如果指定了可选参数 nocache,则每次引用变量时都会调用其处理程序。由于 rewrite 模块当前的限制,当 nocache 变量被 set 指令引用时,其处理程序应始终返回固定长度的值。
由于 js_set 处理程序立即返回结果,它仅支持同步操作。因此,不支持异步操作,例如 r.subrequest() 或 setTimeout()。
自 0.7.7 版本起,该指令可以在server和location级别指定。
| 语法 |
js_shared_dict_zone |
|---|---|
| 默认值 | — |
| 上下文 |
http |
该指令出现在 0.8.0 版本。
设置共享内存区域的 name 和 size,该区域用于存储在 worker 进程之间共享的键值 字典。
默认情况下,共享字典使用字符串作为键和值。可选参数 type 允许将值类型重新定义为 number。
可选参数 timeout 设置所有共享字典条目从区域中移除的超时时间(以毫秒为单位)。如果某些条目需要不同的移除时间,可以使用 add、incr 和 set 方法的 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 |
|---|---|
| 默认值 | — |
| 上下文 |
http, server, location |
该指令出现在 0.5.3 版本。
声明一个 可写 变量。该值可以包含文本、变量及其组合。与使用 set 指令创建的变量不同,重定向后此变量不会被覆盖。
自 0.7.7 版本起,该指令可以在server和location级别指定。
请求参数
每个 HTTP njs 处理程序接收一个参数,即请求 对象。