Appearance
模块 ngx_http_js_module
提示
来自deepseek解释
原文链接:https://nginx.org/en/docs/http/ngx_http_js_module.html
ngx_http_js_module 模块用于在 njs(JavaScript 语言的一个子集)中实现 location 和变量处理程序。下载和安装说明请参见此处。
示例配置
以下示例自 0.4.0 版本起可用。
nginx
http {
# 自 0.9.1 版本起
js_engine qjs;
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;
}
# 自 0.7.0 版本起
location = /fetch {
js_content http.fetch;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
# 自 0.7.0 版本起
location = /crypto {
add_header Hash $hash;
return 200;
}
}
}http.js 文件:
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!");
}
// 自 0.7.0 版本起
async function fetch(r) {
let results = await Promise.all([
ngx.fetch('https://nginx.org/'),
ngx.fetch('https://nginx.org/en/')
]);
r.return(200, JSON.stringify(results, undefined, 4));
}
// 自 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
| 语法 | js_body_filter module.function [buffer_type=string | buffer]; |
| 默认值 | — |
| 上下文 | location, if in location, limit_except |
该指令自 0.5.2 版本起可用。
设置一个 njs 函数作为响应体过滤器。该过滤器函数会在响应体的每个数据块上被调用,参数如下:
r— HTTP 请求对象data— 传入的数据块,根据buffer_type的值可能为字符串或Buffer,默认为字符串。自 0.8.5 起,data值默认隐式转换为有效的 UTF-8 字符串。对于二进制数据,buffer_type应设置为buffer。flags— 包含以下属性的对象:last— 布尔值,若data为最后一个缓冲区则为true
过滤器函数可以通过调用 r.sendBuffer() 将其自身修改后的数据块版本传递给下一个 body 过滤器。例如,将响应体中的所有小写字母转换为大写:
js
function filter(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}如果过滤器函数改变了响应体的长度,则应在 js_header_filter 中清除(如果存在)“Content-Length”响应头,以强制使用分块传输编码:
example.conf:
nginx
location /foo {
# proxy_pass http://localhost:8080;
js_header_filter main.clear_content_length;
js_body_filter main.filter;
}example.js:
js
function clear_content_length(r) {
delete r.headersOut['Content-Length'];
}要停止过滤并将数据块直接传递给客户端而不调用 js_body_filter,可以使用 r.done()。例如,在响应体前添加一些数据:
js
function prepend(r, data, flags) {
r.sendBuffer("XXX");
r.sendBuffer(data, flags);
r.done();
}由于 js_body_filter 处理程序会立即返回其结果,因此仅支持同步操作。异步操作如 r.subrequest() 或 setTimeout() 不被支持。
js_access
| 语法 | js_access module.function; |
| 默认值 | — |
| 上下文 | location, if in location, limit_except |
该指令自 0.9.9 版本起可用。
设置一个 njs 函数作为访问阶段的处理程序。支持异步操作,如 r.subrequest()、ngx.fetch() 和 setTimeout()。
处理程序若未调用 r.return() 或 r.decline() 即返回,则表示授予访问权限。若要拒绝访问或发送自定义响应(例如重定向),处理程序可调用 r.return()。若要使处理程序不发表意见,将决策权交给 satisfy any 下的其他访问检查器,处理程序可调用 r.decline()。
例如:
example.conf:
nginx
location /protected/ {
js_access main.auth;
proxy_pass http://upstream;
}example.js:
js
async function auth(r) {
let reply = await ngx.fetch('http://authsvc/check', {
headers: {Authorization: r.headersIn.Authorization}
});
if (reply.status != 200) {
r.return(401);
return;
}
}
export default {auth};js_content
| 语法 | js_content module.function; |
| 默认值 | — |
| 上下文 | location, if in location, limit_except |
设置一个 njs 函数作为 location 内容处理程序。
自 0.4.0 起,可以引用模块函数。
js_context_reuse
| 语法 | js_context_reuse number; |
| 默认值 | js_context_reuse 128; |
| 上下文 | http, server, location |
该指令自 0.8.6 版本起可用。
设置 QuickJS 引擎可重用的 JS 上下文的最大数量。每个上下文用于单个请求。完成的上下文会被放入可重用上下文的池中。如果池已满,该上下文将被销毁。
js_engine
| 语法 | js_engine njs | qjs; |
| 默认值 | js_engine njs; |
| 上下文 | http, server, location |
该指令自 0.8.6 版本起可用。
设置用于 njs 脚本的 JavaScript 引擎。njs 参数设置 njs 引擎,也是默认值。qjs 参数设置 QuickJS 引擎。
njs 引擎自 1.0.0 起已弃用;新配置应使用 qjs(QuickJS)引擎。
js_fetch_buffer_size
| 语法 | js_fetch_buffer_size size; |
| 默认值 | js_fetch_buffer_size 16k; |
| 上下文 | http, server, location |
该指令自 0.7.4 版本起可用。
设置 Fetch API 用于读写操作的缓冲区大小。
js_fetch_ciphers
| 语法 | js_fetch_ciphers 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 size; |
| 默认值 | js_fetch_max_response_buffer_size 1m; |
| 上下文 | http, server, location |
该指令自 0.7.4 版本起可用。
设置通过 Fetch API 接收的响应的最大大小。
js_fetch_protocols
| 语法 | js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3]; |
| 默认值 | js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2; |
| 上下文 | http, server, location |
该指令自 0.7.0 版本起可用。
为 Fetch API 的 HTTPS 请求启用指定的协议。
js_fetch_timeout
| 语法 | js_fetch_timeout time; |
| 默认值 | js_fetch_timeout 60s; |
| 上下文 | http, server, location |
该指令自 0.7.4 版本起可用。
为 Fetch API 定义读写超时时间。超时仅设置在两次连续的读/写操作之间,而不是整个响应期间。如果在此时间内没有数据传输,连接将被关闭。
js_fetch_trusted_certificate
| 语法 | js_fetch_trusted_certificate file; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.7.0 版本起可用。
指定一个 PEM 格式的可信 CA 证书文件,用于验证 Fetch API 的 HTTPS 证书。
js_fetch_verify
| 语法 | js_fetch_verify on | off; |
| 默认值 | js_fetch_verify on; |
| 上下文 | http, server, location |
该指令自 0.7.4 版本起可用。
启用或禁用 Fetch API 对 HTTPS 服务器证书的验证。
js_fetch_verify_depth
| 语法 | js_fetch_verify_depth number; |
| 默认值 | js_fetch_verify_depth 100; |
| 上下文 | http, server, location |
该指令自 0.7.0 版本起可用。
设置 Fetch API HTTPS 服务器证书链的验证深度。
js_fetch_proxy
| 语法 | js_fetch_proxy url; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.9.4 版本起可用。
为 Fetch API 配置正向代理 URL。该 URL 仅支持 HTTP 协议,并可包含可选的用户凭据,格式为 http://[user:password@]host:port,用于 Basic 认证。同时支持到目标服务器的 HTTP 和 HTTPS 连接。如果 URL 为空,则禁用代理路由。参数值可包含变量。
示例:
nginx
location /fetch {
js_fetch_proxy http://user:pass@proxy.example.com:3128;
js_content main.fetch_handler;
}js_fetch_keepalive
| 语法 | js_fetch_keepalive connections; |
| 默认值 | js_fetch_keepalive 0; |
| 上下文 | http, server, location |
该指令自 0.9.2 版本起可用。
激活到目标服务器的连接缓存。当值大于 0 时,为 Fetch API 启用 keepalive 连接。connections 参数设置每个工作进程缓存中保留的到目标服务器的空闲 keepalive 连接的最大数量。超过此数量时,最近最少使用的连接将被关闭。
在 HTTP 中,缓存为每个有效的 location 配置分别维护。在 http 或 server 级别设置的值会被 location 继承,但每个 location 使用自己的缓存。
缓存的连接会被复用给具有相同协议、主机和端口的请求。启用后,keepalive 假设目标服务器发送有效的 HTTP 响应。
示例:
nginx
location /fetch {
js_fetch_keepalive 32;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
js_content main.fetch_handler;
}js_fetch_keepalive_requests
| 语法 | js_fetch_keepalive_requests number; |
| 默认值 | js_fetch_keepalive_requests 1000; |
| 上下文 | http, server, location |
该指令自 0.9.2 版本起可用。
设置一条 keepalive 连接可通过 Fetch API 服务的最大请求数。达到最大请求数后,连接将被关闭。定期关闭连接对于释放每连接内存分配是必要的。因此,使用过高的最大请求数可能导致内存使用过量,不推荐这样做。
js_fetch_keepalive_time
| 语法 | js_fetch_keepalive_time time; |
| 默认值 | js_fetch_keepalive_time 1h; |
| 上下文 | http, server, location |
该指令自 0.9.2 版本起可用。
限制通过一条 keepalive 连接处理 Fetch API 请求的最大时间。达到此时间后,连接将在后续请求处理完成后关闭。
js_fetch_keepalive_timeout
| 语法 | js_fetch_keepalive_timeout time; |
| 默认值 | js_fetch_keepalive_timeout 60s; |
| 上下文 | http, server, location |
该指令自 0.9.2 版本起可用。
设置 Fetch API 到目标服务器的空闲 keepalive 连接保持打开的超时时间。
js_header_filter
| 语法 | js_header_filter module.function; |
| 默认值 | — |
| 上下文 | location, if in location, limit_except |
该指令自 0.5.1 版本起可用。
设置一个 njs 函数作为响应头过滤器。该指令允许修改响应头的任意头字段。
由于 js_header_filter 处理程序会立即返回其结果,因此仅支持同步操作。异步操作如 r.subrequest() 或 setTimeout() 不被支持。
js_import
| 语法 | js_import module.js | export_name from module.js; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.4.0 版本起可用。
导入一个实现 njs location 和变量处理程序的模块。export_name 用作访问模块函数的命名空间。如果未指定 export_name,则使用模块名称作为命名空间。
nginx
js_import http.js;此处,模块名称 http 用作访问导出的命名空间。如果导入的模块导出 foo(),则使用 http.foo 来引用它。
可以指定多个 js_import 指令。
当在 location 内指定 js_import 时,仅当请求中尚未调用任何 JavaScript 代码时,导入的模块才可见。
每个请求在首次访问 js_set 变量或首次调用 js_content、js_header_filter、js_body_filter 或 js_access 处理程序时创建一个 VM。该 VM 从当时活动的配置作用域克隆而来,请求中的所有后续 JavaScript 调用都复用该 VM。因此,如果上述任何一项在请求被映射到最终 location 之前被引用(例如从 server 级别的 set),则 VM 绑定到外部作用域的导入集,匹配到的 location 中导入的模块将不可见。为避免此问题,应在公共父作用域中声明此类导入。
自 0.7.7 起,该指令可以在 server 和 location 级别指定。
js_include
| 语法 | js_include file; |
| 默认值 | — |
| 上下文 | http |
指定一个在 njs 中实现 location 和变量处理程序的文件:
nginx.conf:
nginx
js_include http.js;
location /version {
js_content version;
}http.js:
js
function version(r) {
r.return(200, njs.version);
}该指令在版本 0.4.0 中已弃用,并在版本 0.7.1 中移除。应改用 js_import 指令。
js_load_http_native_module
| 语法 | js_load_http_native_module path [as name]; |
| 默认值 | — |
| 上下文 | main |
该指令自 0.9.5 版本起可用。
加载一个 原生模块(共享库)供 HTTP JavaScript 代码使用。该指令仅适用于 QuickJS,在使用 njs 内置 JavaScript 引擎时不可用。
path 参数指定共享库文件的绝对路径。可选的 as name 参数为在 JavaScript 代码中导入模块提供别名。如果未指定,则可以使用文件名导入模块。
示例:
nginx
js_load_http_native_module /path/to/mylib.so;
js_load_http_native_module /path/to/other.so as myalias;
http {
js_import main.js;
# ... 其余 http 配置
}在 JavaScript 代码中:
js
// 按文件名导入
import * as mylib from 'mylib.so';
// 按别名导入
import * as myalias from 'myalias';
// 使用导出的函数
let result = mylib.add(5, 10);出于安全原因,该指令仅允许在 main 配置上下文中使用。原生模块以完整的进程权限运行;请使用绝对路径并确保进行适当的代码审查。
js_path
| 语法 | js_path path; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.3.0 版本起可用。
为 njs 模块设置额外的路径。
自 0.7.7 起,该指令可以在 server 和 location 级别指定。
js_periodic
| 语法 | js_periodic module.function [interval=time] [jitter=number] [worker_affinity=mask]; |
| 默认值 | — |
| 上下文 | location |
该指令自 0.8.1 版本起可用。
指定一个按固定时间间隔运行的内容处理程序。该处理程序接收一个会话对象作为其第一个参数,同时也可以访问全局对象如 ngx。
可选的 interval 参数设置两次连续运行之间的间隔,默认为 5 秒。
可选的 jitter 参数设置 location 内容处理程序将被随机延迟的时间范围,默认为无延迟。
默认情况下,js_handler 在工作进程 0 上执行。可选的 worker_affinity 参数允许指定执行 location 内容处理程序的特定工作进程。每个工作进程集合由一个允许的工作进程的位掩码表示。all 掩码允许处理程序在所有工作进程中执行。
示例:
example.conf:
nginx
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:
js
async function handler(s) {
let reply = await ngx.fetch('https://nginx.org/en/docs/njs/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}js_preload_object
| 语法 | js_preload_object name.json | name from file.json; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.7.8 版本起可用。
在配置时预加载一个不可变对象。name 用作全局变量的名称,通过该变量在 njs 代码中访问该对象。如果未指定 name,则使用文件名。
nginx
js_preload_object map.json;此处,map 用作访问预加载对象的名称。
可以指定多个 js_preload_object 指令。
js_set
| 语法 | js_set $variable module.function [nocache]; |
| 默认值 | — |
| 上下文 | http, server, location |
为指定的变量设置一个 njs 函数。
自 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
| 语法 | js_shared_dict_zone zone=name:size [timeout=time] [type=string|number] [evict] [state=file]; |
| 默认值 | — |
| 上下文 | http |
该指令自 0.8.0 版本起可用。
设置共享内存区域的名称和大小,该区域维护工作进程间共享的键值字典。
默认情况下,共享字典使用字符串作为键和值。可选的 type 参数允许将值类型重新定义为数字。
可选的 timeout 参数设置所有共享字典条目从区域中移除的时间(毫秒)。如果某些条目需要不同的移除时间,可以通过 add、incr 和 set 方法的 timeout 参数设置(0.8.5)。
可选的 evict 参数在区域存储耗尽时移除最旧的键值对。
可选的 state 参数指定一个文件,以 JSON 格式保存共享字典状态,并使其在 nginx 重启后持久化(0.9.1)。
示例:
example.conf:
nginx
# 创建一个 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;
# 创建一个 1MB 的字符串值字典,并持久化状态
js_shared_dict_zone zone=persistent:1M state=/tmp/dict.json;example.js:
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
| 语法 | js_var $variable [value]; |
| 默认值 | — |
| 上下文 | http, server, location |
该指令自 0.5.3 版本起可用。
声明一个可写变量。value 可以包含文本、变量及其组合。与使用 set 指令创建的变量不同,该变量在重定向后不会被覆盖。
自 0.7.7 起,该指令可以在 server 和 location 级别指定。
请求参数
每个 HTTP njs 处理程序接收一个参数,即请求对象。