NJS 是 Nginx 提供的 JavaScript 引擎,它允许你在 Nginx 配置中使用 JavaScript 编写复杂的逻辑。通过 NJS,你可以在 Nginx 配置文件中加入 JavaScript 脚本,以增强 Nginx 的功能。NJS 使得 Nginx 具备更高的灵活性,尤其在实现自定义处理、异步任务、数据处理等方面非常有用。

下面是 NJS 的详细入门手册,涵盖安装、基本概念、使用方法、示例等内容。

1. 什么是 NJS?

NJS 是 Nginx 的嵌入式 JavaScript 引擎,允许在 Nginx 配置中运行 JavaScript 脚本。它基于 Google V8 引擎,但与常规 JavaScript 环境(如浏览器)有所不同,运行在 Nginx 的工作进程中,并与 Nginx 的事件循环和模块交互。

2. NJS 安装

在 Nginx 中启用 NJS 需要安装 nginxnjs 模块。NJS 模块并不是 Nginx 默认安装的一部分,因此需要手动安装或编译 Nginx 时启用。

安装 Nginx 和 NJS 模块

1. 安装 Nginx(如果没有安装)

如果你已经有 Nginx 安装,可以跳过这一步。如果没有,请按照你的系统环境安装:

# Ubuntu/Debian 系统
sudo apt update
sudo apt install nginx

# CentOS/RHEL 系统
sudo yum install nginx

2. 安装 NJS 模块

NJS 可以通过 nginx 源码编译时启用,或者在大多数 Linux 发行版中安装已经编译好的 NJS 模块。

  • Ubuntu/Debian 系统sudo apt install libnginx-mod-njs
  • CentOS/RHEL 系统: 需要在 Nginx 中手动编译并启用 NJS 模块。假设你已经安装了 Nginx 源码: ./configure --add-module=/path/to/njs make sudo make install/path/to/njs 中包含 NJS 模块代码。
3. 验证安装

安装完成后,验证 NJS 是否安装成功:

nginx -V

输出中应包含 --with-http_js_module,表示 NJS 模块已正确启用。

3. 配置 Nginx 使用 NJS

在 Nginx 配置文件中使用 JavaScript,需要将 js_includejs_set 等指令添加到配置中。下面是一些常见的配置项:

1. 加载 JavaScript 文件

使用 js_include 加载外部的 JavaScript 文件:

http {
    js_include /path/to/script.js;
    server {
        listen 80;
        location / {
            js_set $my_variable my_js_function;
        }
    }
}

2. 在配置中使用 JavaScript 函数

NJS 允许在 Nginx 配置中定义 JavaScript 函数,这些函数可以与 Nginx 的请求处理流程集成。js_set 用于调用 JavaScript 函数并将返回值设置为变量。

例如,下面是一个简单的 JavaScript 函数示例:

http {
    js_include /path/to/functions.js;
    server {
        listen 80;
        location / {
            js_set $response_var get_dynamic_content;
            add_header X-Dynamic-Content $response_var;
        }
    }
}

/path/to/functions.js 中,定义一个简单的 JavaScript 函数:

function get_dynamic_content(r) {
    return "Hello, Nginx with NJS!";
}

此配置会将 get_dynamic_content 函数的返回值作为 X-Dynamic-Content 响应头的一部分返回。

3. 使用 JavaScript 控制响应

你还可以使用 NJS 来控制 Nginx 的响应。例如,你可以根据某些条件修改响应内容:

http {
    js_include /path/to/functions.js;
    server {
        listen 80;
        location / {
            js_set $dynamic_response check_user_agent;
            add_header X-Dynamic-Response $dynamic_response;
        }
    }
}

check_user_agent 函数的 JavaScript 实现如下:

function check_user_agent(r) {
    if (r.headersIn['User-Agent'].includes('Mozilla')) {
        return "Hello, Firefox user!";
    }
    return "Hello, unknown user!";
}

4. NJS 常用函数

NJS 提供了一些内建的 JavaScript 函数,可以用来处理请求、响应和与 Nginx 进行交互:

  • r.headersIn:访问请求头部。
  • r.uri:获取请求的 URI。
  • r.variables:访问 Nginx 的变量。
  • r.return():发送响应并返回指定状态码。
  • r.readBody():读取请求体。
  • r.sendHeader():发送 HTTP 响应头。

5. 异步操作

NJS 允许使用异步 API 来执行非阻塞操作,如异步读取文件、数据库访问等。

function async_operation(r) {
    r.addOutputHeaders(['Content-Type', 'text/plain']);
    r.return(200, 'Processing...');
    
    setTimeout(function() {
        r.return(200, 'Finished!');
    }, 5000);
}

6. 完整示例:基于请求头的内容动态响应

在这个示例中,我们会根据 User-Agent 请求头的不同来动态响应不同的内容。

http {
    js_include /path/to/dynamic_response.js;
    
    server {
        listen 80;
        
        location / {
            js_set $response dynamic_response_based_on_ua;
            add_header X-Response-Content $response;
            return 200;
        }
    }
}

/path/to/dynamic_response.js 中的 JavaScript:

function dynamic_response_based_on_ua(r) {
    var userAgent = r.headersIn['User-Agent'];
    if (userAgent.includes('Mozilla')) {
        return 'Hello, Mozilla user!';
    }
    return 'Hello, unknown user!';
}

7. NJS 与 Nginx 事件循环

NJS 与 Nginx 的事件循环紧密集成,允许在处理请求时进行非阻塞操作。你可以通过 setTimeoutsetInterval 等异步 API 来执行定时操作,避免阻塞 Nginx 处理其他请求。

8. 性能和限制

NJS 适用于需要扩展 Nginx 功能的场景,但请注意,NJS 是在 Nginx 的工作进程中运行的,所以过于复杂的 JavaScript 脚本可能会影响性能。因此,NJS 更适合用于实现轻量级的、对性能要求不高的脚本逻辑。

9. 调试和日志

NJS 支持通过 ngx.log 输出调试信息。例如:

function my_js_function(r) {
    ngx.log(ngx.INFO, 'Processing request: ' + r.uri);
    return "Processed request";
}

在 Nginx 日志中,你将看到类似如下的信息:

2025/09/23 12:00:00 [info] 12345#0: [dynamic content] Processing request: /path/to/resource

10. 总结

  • NJS 是 Nginx 的嵌入式 JavaScript 引擎,允许你在 Nginx 配置中编写 JavaScript 脚本。
  • 使用场景:动态响应生成、复杂请求处理、自定义逻辑等。
  • 性能考虑:NJS 适合轻量级操作,不适合重度计算或复杂任务。
  • 异步支持:NJS 支持异步操作,可以进行非阻塞的任务处理。

希望这个手册帮助你入门 NJS,如果有更多问题或深入讨论,欢迎继续提问!