<!-- review: finished -->

<a id="external-njs"></a>

# NJS

该模块将 JavaScript 编程语言集成到 Angie 的事件处理模型中,允许使用 JavaScript 脚本扩展服务器功能。它由两个模块组成：

- [HTTP JS](https://cn.angie.software//angie/docs/installation/external-modules/http_js.md#http-js) — 用于处理 HTTP 流量；
- [Stream JS](https://cn.angie.software//angie/docs/installation/external-modules/stream_js.md#stream-js) — 用于处理 TCP/UDP 流量。

<a id="installation-19"></a>

## 安装

要 [安装](https://cn.angie.software//angie/docs/installation/index.md#install-packages) 该模块，请使用以下软件包之一：

- Angie：`angie-module-njs` 或 `angie-module-njs-light`；
- Angie PRO：`angie-pro-module-njs` 或 `angie-pro-module-njs-light`。

<a id="features-1"></a>

## 功能特性

该模块使用 njs（JavaScript 的一个子集）编写的脚本扩展服务器功能，支持实现自定义服务器端逻辑等更多功能：

- 在请求到达代理服务器之前进行复杂的访问控制和安全检查。
- 响应头操作。
- 编写灵活的异步处理程序和内容过滤器。

还提供了一个独立的命令行工具，可以独立于服务器使用，用于开发和调试 njs 脚本。

<a id="loading-the-module-19"></a>

## 加载模块

在 `main{}` 上下文中加载模块：

```nginx
load_module modules/ngx_http_js_module.so;    # 用于 HTTP
load_module modules/ngx_stream_js_module.so;  # 用于 Stream
```

<a id="usage"></a>

## 使用方法

详细文档可在各个模块的章节中找到：

- [HTTP JS](https://cn.angie.software//angie/docs/installation/external-modules/http_js.md#http-js)
- [Stream JS](https://cn.angie.software//angie/docs/installation/external-modules/stream_js.md#stream-js)

<a id="security"></a>

## 安全性

该模块不执行动态代码，特别是从网络接收的代码。使用 njs 执行此类代码的唯一方法是在服务器配置中配置 `js_import` 指令。JavaScript 代码在服务器启动时加载一次。

在该模块的威胁模型中，JavaScript 代码被视为可信来源，就像配置文件和站点证书一样。实际上，这意味着以下几点：

- 由于修改 JavaScript 代码导致的内存内容泄露和其他安全问题不被视为安全问题，而是作为常规错误处理；
- 必须采取措施保护模块使用的 JavaScript 代码；
- 如果配置文件中没有 `js_import` 指令，服务器将受到保护，免受与 JavaScript 相关的漏洞影响。

<a id="command-line-utility"></a>

## 命令行工具

**njs** 命令行工具有助于开发和调试 njs 脚本，与模块一起安装。与模块作为 Angie 的一部分运行时不同，使用该工具时 Angie 对象（`HTTP` 和 `Stream`）不可用。

使用该工具的示例：

```console
$ echo "2**3" | njs -q
8

$ njs

>> globalThis
global {
 njs: njs {
  version: '0.3.9'
 },
 global: [Circular],
 process: process {
  argv: [
   '/usr/bin/njs'
  ],
...
```

<a id="preloaded-objects"></a>

## 预加载对象

对于每个传入请求，该模块会创建一个单独的虚拟机。这提供了许多好处，例如可预测的内存消耗和请求隔离。但是，由于所有请求都是隔离的，如果请求处理程序需要访问任何数据，它必须自己读取。这是低效的，特别是当数据量很大时。

为了解决这个问题，引入了预加载共享对象机制。这些对象被创建为不可变的，并且没有原型链：它们的值不能被更改，属性不能被添加或删除。

以下是在 njs 中使用预加载对象的几个示例：

- 按名称访问属性：
  ```javascript
  preloaded_object.prop_name
  preloaded_object[prop_name]
  ```
- 枚举属性：
  ```javascript
  for (i in preloaded_object_name) {
        // ...
  }
  ```
- 使用 `call()` 应用非修改性内置方法：
  ```javascript
  Array.prototype.filter.call(preloaded_object_name, ...)
  ```

<a id="api-reference"></a>

## API 参考

有关所有 njs 对象、方法和属性的完整参考，请参阅：

- [NJS API 参考](https://cn.angie.software//angie/docs/configuration/njs-reference.md#njs-reference)

<a id="additional-information-20"></a>

## 其他信息

- 官方网站：[https://nginx.org/en/docs/njs/](https://nginx.org/en/docs/njs/)
- 使用示例：[https://github.com/nginx/njs-examples/](https://github.com/nginx/njs-examples/)
