<!-- review: finished -->

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

# NJS API 参考

[NJS](https://cn.angie.software//angie/docs/installation/external-modules/njs.md#external-njs) 模块提供了用于扩展 Angie 功能的对象、方法和属性。

本参考仅包含 NJS 特定的、不符合 ECMAScript 标准的属性、方法和模块。符合 ECMAScript 标准的 NJS 属性和方法的定义可以在 [ECMAScript 规范](http://www.ecma-international.org/ecma-262/) 中找到。

<a id="njs-nginx-objects"></a>

## Angie 对象

<a id="njs-http-request"></a>

### HTTP 请求

- `r.args{}`
- `r.done()`
- `r.error()`
- `r.finish()`
- `r.headersIn{}`
- `r.headersOut{}`
- `r.httpVersion`
- `r.internal`
- `r.internalRedirect()`
- `r.log()`
- `r.method`
- `r.parent`
- `r.remoteAddress`
- `r.requestBody`
- `r.requestBuffer`
- `r.requestText`
- `r.rawHeadersIn[]`
- `r.rawHeadersOut[]`
- `r.responseBody`
- `r.responseBuffer`
- `r.responseText`
- `r.return()`
- `r.send()`
- `r.sendBuffer()`
- `r.sendHeader()`
- `r.setReturnValue()`
- `r.status`
- `r.subrequest()`
- `r.uri`
- `r.rawVariables{}`
- `r.variables{}`
- `r.warn()`

HTTP 请求对象仅在 [HTTP JS](https://cn.angie.software//angie/docs/installation/external-modules/http_js.md#http-js) 模块中可用。在 0.8.5 之前，该对象的所有字符串属性都是字节字符串。

<a id="r-args"></a>

`r.args{}`

> 请求参数对象，只读。

> 查询字符串以对象形式返回。从 0.7.6 开始，重复的键以数组形式返回，键区分大小写，键和值都会进行百分号解码。

> 例如，查询字符串

> ```text
> a=1&b=%32&A=3&b=4&B=two%20words
> ```

> 会被转换为 `r.args`：

> ```javascript
> {a: "1", b: ["2", "4"], A: "3", B: "two words"}
> ```

> 更高级的解析场景可以使用 [Query String](#njs-querystring) 模块和 `$args` 变量来实现，例如：

> ```javascript
> import qs from 'querystring';

> function args(r) {
>     return qs.parse(r.variables.args);
> }
> ```

> 参数对象在首次访问 `r.args` 时进行求值。如果只需要单个参数，例如 `foo`，可以使用 Angie 变量：

> ```javascript
> r.variables.arg_foo
> ```

> 这里，Angie 变量对象返回给定键的第一个值，不区分大小写，不进行百分号解码。

> 要将 `r.args` 转换回字符串，可以使用 Query String 的 `stringify` 方法。

<a id="r-done"></a>

`r.done()`
: 调用此函数后，后续的数据块将直接传递给客户端，而不调用 `js_body_filter` （0.5.2）。只能从 `js_body_filter` 函数中调用。

<a id="r-error"></a>

`r.error(string)`
: 将 `string` 以 `error` 日志级别写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 有硬编码的最大行长度限制，只有字符串的前 2048 字节可以被记录。

<a id="r-finish"></a>

`r.finish()`
: 完成向客户端发送响应。

<a id="r-headers-in"></a>

`r.headersIn{}`
: 传入的请求头对象，只读。
  <br/>
  可以使用以下语法访问 `Foo` 请求头：`headersIn.foo` 或 `headersIn['Foo']`。
  <br/>
  `Authorization`、`Content-Length`、`Content-Range`、`Content-Type`、`ETag`、`Expect`、`From`、`Host`、`If-Match`、`If-Modified-Since`、`If-None-Match`、`If-Range`、`If-Unmodified-Since`、`Max-Forwards`、`Proxy-Authorization`、`Referer`、`Transfer-Encoding` 和 `User-Agent` 请求头只能有一个字段值（0.4.1）。`Cookie` 头中的重复字段值用分号（`;`）分隔。所有其他请求头中的重复字段值用逗号分隔。

<a id="r-headers-out"></a>

`r.headersOut{}`
: 主请求的传出响应头对象，可写。
  <br/>
  如果 `r.headersOut{}` 是子请求的响应对象，它表示响应头。在这种情况下，`Accept-Ranges`、`Connection`、`Content-Disposition`、`Content-Encoding`、`Content-Length`、`Content-Range`、`Date`、`Keep-Alive`、`Server`、`Transfer-Encoding`、`X-Accel-*` 响应头中的字段值可能会被省略。
  <br/>
  可以使用以下语法访问 `Foo` 响应头：`headersOut.foo` 或 `headersOut['Foo']`。
  <br/>
  传出的响应头应该在响应头发送给客户端之前设置；否则，头的更新将被忽略。这意味着 `r.headersOut{}` 在以下情况下有效可写：
  <br/>
  - 在 `js_content` 处理程序中，在调用 `r.sendHeader()` 或 `r.return()` 之前
  - 在 `js_header_filter` 处理程序中
  <br/>
  多值响应头（0.4.0）的字段值可以使用以下语法设置：
  <br/>
  ```javascript
  r.headersOut['Foo'] = ['a', 'b']
  ```
  <br/>
  输出将是：
  <br/>
  ```text
  Foo: a
  Foo: b
  ```
  <br/>
  `Foo` 响应头的所有先前字段值将被删除。
  <br/>
  对于只接受单个字段值的标准响应头（如 `Content-Type`），只有数组的最后一个元素会生效。`Set-Cookie` 响应头的字段值始终以数组形式返回。`Age`、`Content-Encoding`、`Content-Length`、`Content-Type`、`ETag`、`Expires`、`Last-Modified`、`Location`、`Retry-After` 响应头中的重复字段值会被忽略。所有其他响应头中的重复字段值用逗号分隔。

<a id="r-http-version"></a>

`r.httpVersion`
: HTTP 版本，只读。

<a id="r-internal"></a>

`r.internal`
: 布尔值，对于内部 location 为 `true`。

<a id="r-internal-redirect"></a>

`r.internalRedirect(uri)`
: 执行到指定 `uri` 的内部重定向。如果 URI 以 `@` 前缀开头，则被视为命名 location。在新 location 中，所有请求处理从普通 location 的 `NGX_HTTP_SERVER_REWRITE_PHASE` 开始重复，从命名 location 的 `NGX_HTTP_REWRITE_PHASE` 开始重复。因此，重定向到命名 location 不会检查 `client_max_body_size` 限制。重定向的请求变为内部请求，可以访问内部 location。实际的重定向发生在处理程序执行完成后。
  <br/>
  #### NOTE
  重定向后，在目标 location 中启动一个新的 NJS VM，原始 location 中的 VM 停止。Angie 变量的值会保留，可用于向目标 location 传递信息。从 0.5.3 开始，可以使用通过 `js_var` 指令为 HTTP 或 Stream 声明的变量。
  <br/>
  #### NOTE
  从 0.7.4 开始，该方法接受转义的 URI。

<a id="r-log"></a>

`r.log(string)`
: 将 `string` 以 `info` 日志级别写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 有硬编码的最大行长度限制，只有字符串的前 2048 字节可以被记录。

<a id="r-method"></a>

`r.method`
: HTTP 方法，只读。

<a id="r-parent"></a>

`r.parent`
: 引用父请求对象。

<a id="r-remote-address"></a>

`r.remoteAddress`
: 客户端地址，只读。

<a id="r-request-body"></a>

`r.requestBody`
: 该属性在 0.5.0 中已过时，在 0.8.0 中被移除。应该使用 `r.requestBuffer` 或 `r.requestText` 属性代替。

<a id="r-request-buffer"></a>

`r.requestBuffer`
: 客户端请求体（如果尚未写入临时文件）（从 0.5.0 开始）。要确保客户端请求体在内存中，其大小应受 `client_max_body_size` 限制，并且应使用 `client_body_buffer_size` 设置足够的缓冲区大小。该属性仅在 `js_content` 指令中可用。

<a id="r-request-text"></a>

`r.requestText`
: 与 `r.requestBuffer` 相同，但返回一个字符串。注意，它可能会将 UTF-8 编码中无效的字节转换为替换字符。

<a id="r-raw-headers-in"></a>

`r.rawHeadersIn[]`
: 返回键值对数组，完全按照从客户端接收的原样（0.4.1）。
  <br/>
  例如，对于以下请求头：
  <br/>
  ```text
  Host: localhost
  Foo:  bar
  foo:  bar2
  ```
  <br/>
  `r.rawHeadersIn` 的输出将是：
  <br/>
  ```javascript
  [
      ['Host', 'localhost'],
      ['Foo', 'bar'],
      ['foo', 'bar2']
  ]
  ```
  <br/>
  可以使用以下语法收集所有 `foo` 头：
  <br/>
  ```javascript
  r.rawHeadersIn.filter(v=>v[0].toLowerCase() == 'foo').map(v=>v[1])
  ```
  <br/>
  输出将是：
  <br/>
  ```javascript
  ['bar', 'bar2']
  ```
  <br/>
  头字段名称不会转换为小写，重复的字段值不会合并。

<a id="r-raw-headers-out"></a>

`r.rawHeadersOut[]`
: 返回响应头的键值对数组（0.4.1）。头字段名称不会转换为小写，重复的字段值不会合并。

<a id="r-response-body"></a>

`r.responseBody`
: 该属性在 0.5.0 中已弃用，在 0.8.0 中被移除。应该使用 `r.responseBuffer` 或 `r.responseText` 属性代替。

<a id="r-response-buffer"></a>

`r.responseBuffer`
: 包含子请求响应体，只读（从 0.5.0 开始）。`r.responseBuffer` 的大小受 `subrequest_output_buffer_size` 指令限制。

<a id="r-response-text"></a>

`r.responseText`
: 与 `r.responseBuffer` 相同，但返回字符串（从 0.5.0 开始）。注意，它可能会将 UTF-8 编码中无效的字节转换为替换字符。

<a id="r-return"></a>

`r.return(status[, string | Buffer])`
: 向客户端发送带有指定 `status` 的完整响应。响应可以是字符串或 Buffer（0.5.0）。
  <br/>
  可以将重定向 URL（用于代码 301、302、303、307 和 308）或响应正文文本（用于其他代码）指定为第二个参数。

<a id="r-send"></a>

`r.send(string | Buffer)`
: 向客户端发送响应正文的一部分。发送的数据可以是字符串或 Buffer（0.5.0）。

<a id="r-sendbuffer"></a>

`r.sendBuffer(data[, options])`
: 将数据添加到要转发到下一个正文过滤器的数据块链中（0.5.2）。实际转发会在稍后发生，即当前链的所有数据块都处理完毕时。
  <br/>
  数据可以是字符串或 Buffer。`options` 是一个对象，用于覆盖从传入数据块缓冲区派生的 Angie 缓冲区标志。可以使用以下标志覆盖这些标志：
  <br/>
  `last`
  : 布尔值，`true` 表示该缓冲区是最后一个缓冲区。
  <br/>
  `flush`
  : 布尔值，`true` 表示该缓冲区应具有 `flush` 标志。
  <br/>
  该方法只能从 `js_body_filter` 函数中调用。

<a id="r-send-header"></a>

`r.sendHeader()`
: 向客户端发送 HTTP 头。

<a id="r-set-return-value"></a>

`r.setReturnValue(value)`
: 设置 `js_set` 处理程序的返回值（0.7.0）。与普通的 return 语句不同，当处理程序是 JS 异步函数时应使用此方法。例如：
  <br/>
  ```javascript
  async function js_set(r) {
      const digest = await crypto.subtle.digest('SHA-256', r.headersIn.host);
      r.setReturnValue(digest);
  }
  ```

<a id="r-status"></a>

`r.status`
: 状态，可写。

<a id="r-subrequest"></a>

`r.subrequest(uri[, options[, callback]])`
: 使用给定的 `uri` 和 `options` 创建子请求,并安装可选的完成 `callback`。
  <br/>
  子请求与客户端请求共享其输入标头。要向代理服务器发送与原始标头不同的标头,可以使用 `proxy_set_header` 指令。要向代理服务器发送全新的标头集,可以使用 `proxy_pass_request_headers` 指令。
  <br/>
  如果 `options` 是字符串,则它保存子请求参数字符串。否则,:samp:options 应为具有以下键的对象:
  <br/>
  `args`
  : 参数字符串,默认使用空字符串。
  <br/>
  `body`
  : 请求主体,默认使用父请求对象的请求主体。
  <br/>
  `method`
  : HTTP 方法,默认使用 `GET` 方法。
  <br/>
  `detached`
  : 布尔标志(0.3.9);如果为 `true`,则创建的子请求是分离的子请求。对分离子请求的响应将被忽略。与普通子请求不同,分离的子请求可以在变量处理程序内创建。`detached` 标志和 callback 参数是互斥的。
  <br/>
  完成 `callback` 接收一个子请求响应对象,其方法和属性与父请求对象相同。
  <br/>
  从 0.3.8 开始,如果未提供 `callback`,则返回解析为子请求响应对象的 `Promise` 对象。
  <br/>
  例如,要查看子请求中的所有响应标头:
  <br/>
  ```javascript
  async function handler(r) {
      const reply = await r.subrequest('/path');
  <br/>
      for (const h in reply.headersOut) {
          r.log(`${h}: ${reply.headersOut[h]}`);
      }
  <br/>
      r.return(200);
  }
  ```

<a id="r-uri"></a>

`r.uri`
: 请求中的当前 URI,已规范化,只读。

<a id="r-raw-variables"></a>

`r.rawVariables{}`
: Angie 变量作为 Buffers,可写(自 0.5.0 起)。

<a id="r-variables"></a>

`r.variables{}`
: Angie 变量对象,可写(自 0.2.8 起)。
  <br/>
  例如,要获取 `$foo` 变量,可以使用以下语法之一:
  <br/>
  ```javascript
  r.variables['foo']
  r.variables.foo
  ```
  <br/>
  从 0.8.6 开始,可以使用以下语法访问正则表达式捕获:
  <br/>
  ```javascript
  r.variables['1']
  r.variables[1]
  ```
  <br/>
  Angie 对在 `angie.conf` 中引用的变量和未引用的变量的处理方式不同。当变量被引用时,它可能是可缓存的,但当它未被引用时,它始终是不可缓存的。例如,当 `$request_id` 变量仅从 NJS 访问时,每次求值时它都有一个新值。但是,当 `$request_id` 被引用时,例如:
  <br/>
  ```nginx
  proxy_set_header X-Request-Id $request_id;
  ```
  <br/>
  `r.variables.request_id` 每次都返回相同的值。
  <br/>
  变量可写的条件是:
  <br/>
  - 它是使用 HTTP 或 Stream 的 `js_var` 指令创建的(自 0.5.3 起)
  - 它在 Angie 配置文件中被引用
  <br/>
  即便如此,某些内置变量仍然无法被赋值(例如 `$http_`)。

<a id="r-warn"></a>

`r.warn(string)`
: 在 `warning` 日志级别将 `string` 写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 具有硬编码的最大行长度限制,因此只能记录字符串的前 2048 个字节。

<a id="njs-stream-session"></a>

### Stream 会话

- `s.allow()`
- `s.decline()`
- `s.deny()`
- `s.done()`
- `s.error()`
- `s.log()`
- `s.off()`
- `s.on()`
- `s.remoteAddress`
- `s.rawVariables{}`
- `s.send()`
- `s.sendDownstream()`
- `s.sendUpstream()`
- `s.status`
- `s.setReturnValue()`
- `s.variables{}`
- `s.warn()`

流会话对象仅在 [Stream JS](https://cn.angie.software//angie/docs/installation/external-modules/stream_js.md#stream-js) 模块中可用。在 0.8.5 之前,该对象的所有字符串属性都是字节字符串。

<a id="njs-s-allow"></a>

`s.allow()`
: `s.done(0)` 的别名(0.2.4)。

<a id="njs-s-decline"></a>

`s.decline()`
: `s.done(-5)` 的别名(0.2.4)。

<a id="njs-s-deny"></a>

`s.deny()`
: `s.done(403)` 的别名(0.2.4)。

<a id="njs-s-done"></a>

`s.done([code])`
: 将当前阶段处理程序的退出 `code` 设置为代码值,默认为 `0`。实际的终结发生在 js 处理程序完成并且所有待处理事件(例如来自 `ngx.fetch()` 或 `setTimeout()` 的事件)都被处理之后(0.2.4)。
  <br/>
  可能的代码值:
  <br/>
  - `0` — 成功终结,将控制权传递给下一个阶段
  - `-5` — 未决定,将控制权传递给当前阶段的下一个处理程序(如果有)
  - `403` — 访问被禁止
  <br/>
  只能从阶段处理程序函数调用:`js_access` 或 `js_preread`。

<a id="njs-s-error"></a>

`s.error(string)`
: 在 `error` 日志级别将发送的 `string` 写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 具有硬编码的最大行长度限制,因此只能记录字符串的前 2048 个字节。

<a id="s-log"></a>

`s.log(string)`
: 在 `info` 日志级别将发送的 `string` 写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 具有硬编码的最大行长度限制,因此只能记录字符串的前 2048 个字节。

<a id="s-off"></a>

`s.off(eventName)`
: 注销由 `s.on()` 方法设置的回调(0.2.4)。

<a id="s-on"></a>

`s.on(event, callback)`
: 为指定的 `event` 注册 `callback` (0.2.4)。
  <br/>
  `event` 可以是以下字符串之一:
  <br/>
  `upload`
  : 来自客户端的新数据(字符串)。
  <br/>
  `download`
  : 发送到客户端的新数据(字符串)。
  <br/>
  `upstream`
  : 来自客户端的新数据(Buffer)(自 0.5.0 起)。
  <br/>
  `downstream`
  : 发送到客户端的新数据(Buffer)(自 0.5.0 起)。
  <br/>
  完成回调具有以下原型:`callback(data, flags)`,其中 `data` 是字符串或 Buffer(取决于事件类型);:samp:flags 是具有以下属性的对象:
  <br/>
  `last`
  : 布尔值,:samp:true 表示数据是最后一个缓冲区。

<a id="s-remote-address"></a>

`s.remoteAddress`
: 客户端地址,只读。

<a id="s-raw-variables"></a>

`s.rawVariables`
: Angie 变量作为 Buffers,可写(自 0.5.0 起)。

<a id="s-send"></a>

`s.send(data[, options])`
: 将数据添加到将在正向方向转发的数据块链中:在下载回调中发送到客户端;在上传中发送到上游服务器(0.2.4)。实际转发会在稍后发生,即当前链的所有数据块都处理完毕时。
  <br/>
  数据可以是字符串或 Buffer(0.5.0)。`options` 是一个对象,用于覆盖从传入数据块缓冲区派生的 Angie 缓冲区标志。可以使用以下标志覆盖这些标志:
  <br/>
  `last`
  : 布尔值,:samp:true 表示该缓冲区是最后一个缓冲区。
  <br/>
  `flush`
  : 布尔值,:samp:true 表示该缓冲区应具有 `flush` 标志。
  <br/>
  该方法可以在每次回调调用中多次调用。

<a id="s-send-downstream"></a>

`s.sendDownstream()`
: 与 `s.send()` 相同,但它始终将数据发送到客户端(自 0.7.8 起)。

<a id="s-send-upstream"></a>

`s.sendUpstream()`
: 与 `s.send()` 相同,但它始终从客户端发送数据(自 0.7.8 起)。

<a id="s-status"></a>

`s.status`
: 会话状态代码,:samp:$status 变量的别名,只读(自 0.5.2 起)。

<a id="s-set-return-value"></a>

`s.setReturnValue(value)`
: 设置 `js_set` 处理程序的返回值(0.7.0)。与普通的 return 语句不同,当处理程序是 JS 异步函数时应使用此方法。例如:
  <br/>
  ```javascript
  async function js_set(r) {
      const digest = await crypto.subtle.digest('SHA-256', r.headersIn.host);
      r.setReturnValue(digest);
  }
  ```

<a id="s-variables"></a>

`s.variables{}`
: Angie 变量对象,可写(自 0.2.8 起)。变量只有在 Angie 配置文件中被引用时才可写。即便如此,某些内置变量仍然无法被赋值。

<a id="s-warn"></a>

`s.warn(string)`
: 在 `warning` 日志级别将发送的 `string` 写入错误日志。
  <br/>
  #### NOTE
  由于 Angie 具有硬编码的最大行长度限制,因此只能记录字符串的前 2048 个字节。

<a id="njs-periodic-session"></a>

### 周期会话

- `PeriodicSession.rawVariables{}`
- `PeriodicSession.variables{}`

`Periodic Session` 对象作为 HTTP 和 Stream 的 `js_periodic` 处理程序的第一个参数提供(自 0.8.1 起)。

`PeriodicSession.rawVariables{}`
: Angie 变量作为 Buffers,可写。

`PeriodicSession.variables{}`
: Angie 变量对象,可写。

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

### Headers

- `Headers()`
- `Headers.append()`
- `Headers.delete()`
- `Headers.get()`
- `Headers.getAll()`
- `Headers.forEach()`
- `Headers.has()`
- `Headers.set()`

Fetch API 的 `Headers` 接口自 0.5.1 起可用。

可以使用 `Headers()` 构造函数创建新的 `Headers` 对象(自 0.7.10 起):

`Headers([init])`
: `init`
  : 包含用于预填充 `Headers` 对象的 HTTP 标头的对象,可以是 `string`、名称-值对的 `array`,或现有的 `Headers` 对象。

可以使用以下属性和方法创建新的 `Headers` 对象:

`append()`
: 向 `Headers` 对象中的现有标头追加新值,如果标头不存在则添加该标头(自 0.7.10 起)。

`delete()`
: 从 `Headers` 对象中删除标头(自 0.7.10 起)。

`get()`
: 返回包含指定名称的所有标头值的字符串,值之间用逗号和空格分隔。

`getAll(name)`
: 返回包含指定名称的所有标头值的数组。

`forEach()`
: 对 `Headers` 对象中的每个键/值对执行一次提供的函数(自 0.7.10 起)。

`has()`
: 返回布尔值,指示是否存在具有指定名称的标头。

`set()`
: 为 `Headers` 对象内的现有标头设置新值,如果标头不存在则添加该标头(自 0.7.10 起)。

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

### Request

- `Request()`
- `Request.arrayBuffer()`
- `Request.bodyUsed`
- `Request.cache`
- `Request.credentials`
- `Request.headers`
- `Request.json()`
- `Request.method`
- `Request.mode`
- `Request.text()`
- `Request.url`

Fetch API 的 `Request` 接口自 0.7.10 起可用。

可以使用 `Request()` 构造函数创建新的 `Request` 对象:

`Request[resource[, options]])`
: 创建一个可以稍后传递给 `ngx.fetch()` 的 `Request` 对象来获取。`resource` 可以是 URL 或现有的 `Request` 对象。`options` 是可选参数,应为具有以下键的对象:
  <br/>
  `body`
  : 请求主体,默认为空。
  <br/>
  `headers`
  : 响应标头对象——包含用于预填充 `Headers` 对象的 HTTP 标头的对象,可以是 `string`、名称-值对的 `array`,或现有的 `Headers` 对象。
  <br/>
  `method`
  : HTTP 方法,默认使用 GET 方法。

可以使用以下属性和方法创建新的 `Request` 对象:

`arrayBuffer()`
: 返回一个 `Promise`,该 Promise 解析为 `ArrayBuffer`。

`bodyUsed`
: 布尔值,如果主体已在请求中使用则为 `true`。

`cache`
: 包含请求的缓存模式。

`credentials`
: 包含请求的凭据,默认为 `same-origin`。

`headers`
: 与 `Request` 关联的只读 `Headers` 对象。

`json()`
: 返回一个 `Promise`,该 Promise 解析为将请求主体解析为 JSON 的结果。

`method`
: 包含请求方法。

`mode`
: 包含请求的模式。

`text()`
: 返回一个 `Promise`,该 Promise 解析为请求主体的字符串表示形式。

`url`
: 包含请求的 URL。

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

### Response

- `Response()`
- `Response.arrayBuffer()`
- `Response.bodyUsed`
- `Response.headers`
- `Response.json()`
- `Response.ok`
- `Response.redirected`
- `Response.status`
- `Response.statusText`
- `Response.text()`
- `Response.type`
- `Response.url`

`Response` 接口自 0.5.1 起可用。

可以使用 `Response()` 构造函数创建新的 `Response` 对象(自 0.7.10 起):

`Response[body[, options]])`
: 创建 `Response` 对象。`body` 是可选参数,可以是 `string` 或 `buffer`,默认为 `null`。`options` 是可选参数,应为具有以下键的对象:
  <br/>
  `headers`
  : 响应标头对象——包含用于预填充 `Headers` 对象的 HTTP 标头的对象,可以是 `string`、名称-值对的 `array`,或现有的 `Headers` 对象。
  <br/>
  `status`
  : 响应的状态码。
  <br/>
  `statusText`
  : 与状态码对应的状态消息。

可以使用以下属性和方法创建新的 `Response()` 对象:

`arrayBuffer()`
: 获取 `Response` 流并读取至完成。返回一个 `Promise`,该 Promise 解析为 `ArrayBuffer`。

`bodyUsed`
: 布尔值,如果主体已被读取则为 `true`。

`headers`
: 与 `Response` 关联的只读 `Headers` 对象。

`json()`
: 获取 `Response` 流并读取至完成。返回一个 `Promise`,该 Promise 解析为将主体文本解析为 JSON 的结果。

`ok`
: 布尔值,如果响应成功(状态码在 200–299 之间)则为 `true`。

`redirected`
: 布尔值,如果响应是重定向的结果则为 `true`。

`status`
: 响应的状态码。

`statusText`
: 与状态码对应的状态消息。

`text()`
: 获取 `Response` 流并读取至完成。返回一个 `Promise`,该 Promise 解析为字符串。

`type`
: 响应的类型。

`url`
: 响应的 URL。

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

### ngx

- `ngx.build`
- `ngx.conf_file_path`
- `ngx.conf_prefix`
- `ngx.error_log_path`
- `ngx.fetch()`
- `ngx.log()`
- `ngx.prefix`
- `ngx.version`
- `ngx.version_number`
- `ngx.worker_id`

`ngx` 全局对象自 0.5.0 起可用。

`ngx.build`
: 包含可选 Angie 构建名称的字符串,对应于 configure 脚本的 `--build=name` 参数,默认为 `""` (0.8.0)。

`ngx.conf_file_path`
: 包含当前 Angie 配置文件的文件路径的字符串(0.8.0)。

`ngx.conf_prefix`
: 包含 Angie 配置前缀的文件路径的字符串——Angie 当前查找配置的目录(0.7.8)。

`ngx.error_log_path`
: 包含当前错误日志文件的文件路径的字符串(0.8.0)。

<a id="ngx-fetch"></a>

`ngx.fetch(resource, [options])`
: 发起请求以获取 `resource` (0.5.1),可以是 URL 或 `Request` 对象(0.7.10)。返回一个 `Promise`,该 Promise 解析为 `Response` 对象。从 0.7.0 开始,支持 `https://` 协议;不处理重定向。
  <br/>
  如果 `resource` 中的 URL 指定为域名,则使用解析器进行解析。如果指定了 `https://` 协议,则应配置 `js_fetch_trusted_certificate` 指令以对 `resource` 的 HTTPS 服务器进行身份验证。
  <br/>
  `options` 参数应为包含以下键的对象:
  <br/>
  `body`
  : 请求主体,默认为空。
  <br/>
  `buffer_size`
  : 读取响应的缓冲区大小,默认为 `4096`。
  <br/>
  `headers`
  : 请求头对象。
  <br/>
  `max_response_body_size`
  : 响应主体的最大大小(以字节为单位),默认为 `32768`。
  <br/>
  `method`
  : HTTP 方法,默认使用 `GET` 方法。
  <br/>
  `verify`
  : 启用或禁用 HTTPS 服务器证书验证,默认为 `true` (0.7.0)。
  <br/>
  示例:
  <br/>
  ```javascript
  let reply = await ngx.fetch('http://example.com/');
  let body = await reply.text();
  <br/>
  r.return(200, body);
  ```

`ngx.log(level, message)`
: 使用指定的日志级别将消息写入错误日志。`level` 参数指定日志级别之一;:samp:message 参数可以是字符串或 Buffer。可以指定以下日志级别:`ngx.INFO`、`ngx.WARN` 和 `ngx.ERR`。
  <br/>
  #### NOTE
  由于 Angie 具有硬编码的最大行长度限制,因此只能记录字符串的前 2048 个字节。

`ngx.prefix`
: 包含 Angie 前缀文件路径的字符串 — 保存服务器文件的目录(0.8.0)。

`ngx.version`
: 包含 Angie 版本的字符串,例如:`1.25.0` (0.8.0)。

`ngx.version_number`
: 包含 Angie 版本的数字,例如:`1025000` (0.8.0)。

`ngx.worker_id`
: 对应于 Angie 内部工作进程 ID 的数字,该值介于 `0` 和 `worker_processes` 指令中指定的值之间(0.8.0)。

<a id="njs-ngx-shared"></a>

### ngx.shared

`ngx.shared` 全局对象从 0.8.0 开始可用。

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

#### SharedDict

- `ngx.shared.SharedDict.add()`
- `ngx.shared.SharedDict.capacity`
- `ngx.shared.SharedDict.clear()`
- `ngx.shared.SharedDict.delete()`
- `ngx.shared.SharedDict.freeSpace()`
- `ngx.shared.SharedDict.get()`
- `ngx.shared.SharedDict.has()`
- `ngx.shared.SharedDict.incr()`
- `ngx.shared.SharedDict.items()`
- `ngx.shared.SharedDict.keys()`
- `ngx.shared.SharedDict.name`
- `ngx.shared.SharedDict.pop()`
- `ngx.shared.SharedDict.replace()`
- `ngx.shared.SharedDict.set()`
- `ngx.shared.SharedDict.size()`
- `ngx.shared.SharedDict.type`

共享字典对象从 0.8.0 开始可用。共享字典的名称、类型和大小通过 HTTP 或 Stream 中的 `js_shared_dict_zone` 指令设置。

`SharedDict()` 对象具有以下属性和方法:

`ngx.shared.SharedDict.add(key, value [,timeout])`
: 仅当键尚不存在时,才为字典中的指定 `key` 设置 `value`。`key` 参数是表示要添加项的键的字符串;:samp:value 参数是要添加项的值。
  <br/>
  可选的 `timeout` 参数以毫秒为单位指定,并覆盖 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `timeout` 参数(从 0.8.5 开始)。当某些键预期具有唯一的超时时间时,这可能很有用。
  <br/>
  如果值已成功添加到 `SharedDict` 字典,则返回 `true`;如果键已存在于字典中,则返回 `false`。如果 `SharedDict` 字典中没有足够的可用空间,则抛出 `SharedMemoryError`。如果 `value` 的类型与此字典预期的类型不同,则抛出 `TypeError`。

`ngx.shared.SharedDict.capacity`
: 返回 `SharedDict` 字典的容量,对应于 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `size` 参数。

`ngx.shared.SharedDict.clear()`
: 从 `SharedDict` 字典中删除所有项。

`ngx.shared.SharedDict.delete(key)`
: 从 `SharedDict` 字典中删除与指定键关联的项;如果字典中的项存在并已删除,则返回 `true`,否则返回 `false`。

`ngx.shared.SharedDict.freeSpace()`
: 返回可用页面大小(以字节为单位)。如果大小为零,则 `SharedDict` 字典仍将接受新值(如果已占用页面中有空间)。

`ngx.shared.SharedDict.get(key)`
: 通过其 `key` 检索项;返回与 `key` 关联的值,如果没有则返回 `undefined`。

`ngx.shared.SharedDict.has(key)`
: 通过其 `key` 搜索项;如果存在此类项,则返回 `true`,否则返回 `false`。

`ngx.shared.SharedDict.incr(key,delta[[,init], timeout])`
: 将与 `key` 关联的整数值增加 `delta`。`key` 参数是字符串;:samp:delta 参数是要增加或减少值的数字。如果键不存在,则该项将初始化为可选的 `init` 参数,默认为 `0`。
  <br/>
  可选的 `timeout` 参数以毫秒为单位指定,并覆盖 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `timeout` 参数(从 0.8.5 开始)。当某些键预期具有唯一的超时时间时,这可能很有用。
  <br/>
  返回新值。如果 `SharedDict` 字典中没有足够的可用空间,则抛出 `SharedMemoryError`。如果此字典不期望数字,则抛出 `TypeError`。
  <br/>
  #### NOTE
  仅当使用 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `type=number` 参数声明字典类型时,才能使用此方法。

`ngx.shared.SharedDict.items([maxCount])`
: 返回 `SharedDict` 字典键值项的数组(从 0.8.1 开始)。`maxCount` 参数设置要检索的最大项数,默认为 `1024`。

`ngx.shared.SharedDict.keys([maxCount])`
: 返回 `SharedDict` 字典键的数组。`maxCount` 参数设置要检索的最大键数,默认为 `1024`。

`ngx.shared.SharedDict.name`
: 返回 `SharedDict` 字典的名称,对应于 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `zone=` 参数。

`ngx.shared.SharedDict.pop(key)`
: 从 `SharedDict` 字典中删除与指定 `key` 关联的项;返回与 `key` 关联的值,如果没有则返回 `undefined`。

`ngx.shared.SharedDict.replace(key, value)`
: 仅当键已存在时,才替换指定 `key` 的 `value`;如果值已成功替换,则返回 `true`,如果键在 `SharedDict` 字典中不存在,则返回 `false`。如果 `SharedDict` 字典中没有足够的可用空间,则抛出 `SharedMemoryError`。如果 `value` 的类型与此字典预期的类型不同,则抛出 `TypeError`。

`ngx.shared.SharedDict.set(key, value [,timeout])`
: 为指定的 `key` 设置 `value`;返回此 `SharedDict` 字典(用于方法链)。
  <br/>
  可选的 `timeout` 参数以毫秒为单位指定,并覆盖 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `timeout` 参数(从 0.8.5 开始)。当某些键预期具有唯一的超时时间时,这可能很有用。

`ngx.shared.SharedDict.size()`
: 返回 `SharedDict` 字典的项数。

`ngx.shared.SharedDict.type`
: 返回 `string` 或 `number`,对应于 HTTP 或 Stream 中 `js_shared_dict_zone` 指令的 `type=` 参数设置的 `SharedDict` 字典类型。

<a id="njs-builtin-objects"></a>

## 内置对象

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

### console

- `console.error()`
- `console.info()`
- `console.log()`
- `console.time()`
- `console.timeEnd()`
- `console.warn()`

`console` 对象从 Angie 0.8.2 开始可用,从 CLI 0.2.6 开始可用。

`console.error(msg[, msg2 ...])`
: 输出一条或多条错误消息。消息可以是字符串或对象。

`console.info(msg[, msg2 ...])`
: 输出一条或多条信息消息。消息可以是字符串或对象。

`console.log(msg[, msg2 ...])`
: 输出一条或多条日志消息。消息可以是字符串或对象。

`console.time(label)`
: 启动一个计时器,可以跟踪操作所需的时间。`label` 参数允许命名不同的计时器。如果使用相同的名称调用 `console.timeEnd()`,则将输出自计时器启动以来经过的时间(以毫秒为单位)。

`console.timeEnd(label)`
: 停止先前由 `console.time()` 启动的计时器。`label` 参数允许命名不同的计时器。

`console.warn(msg[, msg2 ...])`
: 输出一条或多条警告消息。消息可以是字符串或对象。

<a id="njs-builtin-crypto"></a>

### crypto

- `crypto.getRandomValues()`
- `crypto.subtle.encrypt()`
- `crypto.subtle.decrypt()`
- `crypto.subtle.deriveBits()`
- `crypto.subtle.deriveKey()`
- `crypto.subtle.digest()`
- `crypto.subtle.exportKey()`
- `crypto.subtle.generateKey()`
- `crypto.subtle.importKey()`
- `crypto.subtle.sign()`
- `crypto.subtle.verify()`

`crypto` 对象是一个全局对象,允许使用加密功能(自 0.7.0 起)。

`crypto.getRandomValues(typedArray)`
: 获取加密强度的随机值。返回作为 `typedArray` 传递的同一数组,但其内容被替换为新生成的随机数。可能的值:
  <br/>
  `typedArray`
  : 可以是 `Int8Array`、`Int16Array`、`Uint16Array`、`Int32Array` 或 `Uint32Array`。

`crypto.subtle.encrypt(algorithm, key, data)`
: 使用提供的 `algorithm` 和 `key` 加密 `data`。返回一个 `Promise`,该 Promise 将使用包含密文的 `ArrayBuffer` 来兑现。可能的值:
  <br/>
  `algorithm`
  : 一个对象,指定要使用的算法以及所需的任何额外参数:
    <br/>
    - 对于 `RSA-OAEP`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `RSA-OAEP`:
        ```javascript
        crypto.subtle.encrypt({name: "RSA-OAEP"}, key, data)
        ```
    - 对于 `AES-CTR`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-CTR`。
    <br/>
      `counter`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView` — 计数器块的初始值,必须为 16 字节长(AES 块大小)。此块最右边的 length 位用于计数器,其余部分用于随机数。例如,如果 length 设置为 64,则 counter 的前半部分是随机数,后半部分用于计数器。
    <br/>
      `length`
      : 计数器块中用于实际计数器的位数。计数器必须足够大,以免回绕。
    - 对于 `AES-CBC`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-CBC`。
    <br/>
      `iv`
      : 初始化向量,是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,必须为 16 字节,不可预测,最好是加密随机的。但是,它不需要保密,例如,它可以与密文一起未加密传输。
    - 对于 `AES-GCM`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-GCM`。
    <br/>
      `iv`
      : 初始化向量,是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,必须为 16 字节,并且对于使用给定密钥执行的每个加密操作必须是唯一的。
    <br/>
      `additionalData`
      : (可选)是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,包含不会被加密但将与加密数据一起进行身份验证的附加数据。如果指定了 `additionalData`,则必须在相应的 `decrypt()` 调用中指定相同的数据:如果提供给 `decrypt()` 调用的数据与原始数据不匹配,解密将抛出异常。`additionalData` 的位长度必须小于 `2^64 - 1`。
    <br/>
      `tagLength`
      : (可选,默认为 `128`) - 一个 `number`,确定在加密操作中生成的身份验证标签的位大小,并在相应的解密中用于身份验证。可能的值: `32`、`64`、`96`、`104`、`112`、`120` 或 `128`。AES-GCM 规范建议应为 `96`、`104`、`112`、`120` 或 `128`,尽管在某些应用程序中 `32` 或 `64` 位可能是可接受的。
  <br/>
  `key`
  : 一个 `CryptoKey`,包含用于加密的密钥。
  <br/>
  `data`
  : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,包含要加密的数据(也称为明文)。

`crypto.subtle.decrypt(algorithm, key, data)`
: 解密加密的数据。返回一个包含解密数据的 `Promise`。可能的值:
  <br/>
  `algorithm`
  : 一个对象,指定要使用的算法以及所需的任何额外参数。为额外参数提供的值必须与传递到相应 `encrypt()` 调用中的值匹配。
    <br/>
    - 对于 `RSA-OAEP`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `RSA-OAEP`:
        ```javascript
        crypto.subtle.encrypt({name: "RSA-OAEP"}, key, data)
        ```
    - 对于 `AES-CTR`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-CTR`。
    <br/>
      `counter`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView` — 计数器块的初始值,必须为 16 字节长(AES 块大小)。此块最右边的 length 位用于计数器,其余部分用于随机数。例如,如果 length 设置为 64,则 counter 的前半部分是随机数,后半部分用于计数器。
    <br/>
      `length`
      : 计数器块中用于实际计数器的位数。计数器必须足够大,以免回绕。
    - 对于 `AES-CBC`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-CBC`。
    <br/>
      `iv`
      : 初始化向量,是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,必须为 16 字节,不可预测,最好是加密随机的。但是,它不需要保密(例如,它可以与密文一起未加密传输)。
    - 对于 `AES-GCM`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `AES-GCM`。
    <br/>
      `iv`
      : 初始化向量,是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,必须为 16 字节,并且对于使用给定密钥执行的每个加密操作必须是唯一的。
    <br/>
      `additionalData`
      : (可选)是一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,包含不会被加密但将与加密数据一起进行身份验证的附加数据。如果指定了 `additionalData`,则必须在相应的 `decrypt()` 调用中指定相同的数据:如果提供给 `decrypt()` 调用的数据与原始数据不匹配,解密将抛出异常。`additionalData` 的位长度必须小于 `2^64 - 1`。
    <br/>
      `tagLength`
      : (可选,默认为 `128`) - 一个 `number`,确定在加密操作中生成的身份验证标签的位大小,并在相应的解密中用于身份验证。可能的值: `32`、`64`、`96`、`104`、`112`、`120` 或 `128`。AES-GCM 规范建议应为 `96`、`104`、`112`、`120` 或 `128`,尽管在某些应用程序中 `32` 或 `64` 位可能是可接受的。
  <br/>
  `key`
  : 一个 `CryptoKey`,包含用于解密的密钥。如果使用 `RSA-OAEP`,这是 `CryptoKeyPair` 对象的 `privateKey` 属性。
  <br/>
  `data`
  : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,包含要解密的数据(也称为密文)。

`crypto.subtle.deriveBits(algorithm, baseKey, length)`
: 从基础密钥派生位数组。返回一个 `Promise`,该 Promise 将使用包含派生位的 `ArrayBuffer` 来兑现。可能的值:
  <br/>
  `algorithm`
  : 一个对象,定义要使用的派生算法:
    <br/>
    - 对于 `HKDF`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `HKDF`。
    <br/>
      `hash`
      : 一个字符串,包含要使用的摘要算法: `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `salt`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示与 `digest` 函数的输出长度相同的随机或伪随机值。与传递到 `deriveKey()` 中的输入密钥材料不同,salt 不需要保密。
    <br/>
      `info`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示特定于应用程序的上下文信息,用于将派生密钥绑定到应用程序或上下文,并允许在使用相同输入密钥材料的同时为不同上下文派生不同的密钥。此属性是必需的,但可以是空缓冲区。
    - 对于 `PBKDF2`,传递一个具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `PBKDF2`。
    <br/>
      `hash`
      : 一个字符串,包含要使用的摘要算法: `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `salt`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示至少 `16` 字节的随机或伪随机值。与传递到 `deriveKey()` 中的输入密钥材料不同,salt 不需要保密。
    <br/>
      `iterations`
      : 一个 `number`,表示在 `deriveKey()` 中哈希函数将被执行的次数。
    - 对于 `ECDH`,传递具有以下键的对象(自 0.9.1 起):
    <br/>
      `name`
      : 一个字符串,应设置为 `ECDH`。
    <br/>
      `public`
      : 一个 `CryptoKey`,表示另一方的公钥。该密钥必须使用与基础密钥相同的曲线生成。
  <br/>
  `baseKey`
  : 一个 `CryptoKey`,表示派生算法的输入 - 派生函数的初始密钥材料:例如,对于 `PBKDF2`,它可能是一个密码,使用 `crypto.subtle.importKey()` 作为 `CryptoKey` 导入。
  <br/>
  `length`
  : 一个数字,表示要派生的比特数。为了浏览器兼容性,该数字应该是 `8` 的倍数。

`crypto.subtle.deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages)`
: 从主密钥派生一个秘密密钥。可能的值:
  <br/>
  `algorithm`
  : 一个对象,定义要使用的派生算法:
    <br/>
    - 对于 `HKDF`,传递具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `HKDF`。
    <br/>
      `hash`
      : 一个字符串,包含要使用的摘要算法: `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `salt`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示与 `digest` 函数输出长度相同的随机或伪随机值。与传递给 `deriveKey()` 的输入密钥材料不同,盐不需要保密。
    <br/>
      `info`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示特定于应用程序的上下文信息,用于将派生密钥绑定到应用程序或上下文,并允许在使用相同输入密钥材料的同时为不同上下文派生不同的密钥。此属性是必需的,但可以是空缓冲区。
    - 对于 `PBKDF2`,传递具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `PBKDF2`。
    <br/>
      `hash`
      : 一个字符串,包含要使用的摘要算法: `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `salt`
      : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,表示至少 `16` 字节的随机或伪随机值。与传递给 `deriveKey()` 的输入密钥材料不同,盐不需要保密。
    <br/>
      `iterations`
      : 一个 `number`,表示在 `deriveKey()` 中哈希函数将被执行的次数。
    - 对于 `ECDH`,传递具有以下键的对象(自 0.9.1 起):
    <br/>
      `name`
      : 一个字符串,应设置为 `ECDH`。
    <br/>
      `publicKey`
      : 一个 `CryptoKey`,表示另一方的公钥。该密钥必须使用与基础密钥相同的曲线生成。
  <br/>
  `baseKey`
  : 一个 `CryptoKey`,表示派生算法的输入 - 派生函数的初始密钥材料:例如,对于 `PBKDF2`,它可能是一个密码,使用 `crypto.subtle.importKey()` 作为 `CryptoKey` 导入。
  <br/>
  `derivedKeyAlgorithm`
  : 一个对象,定义派生密钥将用于的算法:
    <br/>
    - 对于 `HMAC`,传递具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应设置为 `HMAC`。
    <br/>
      `hash`
      : 一个字符串,包含要使用的摘要函数的名称: `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `length`
      : (可选)是一个 `number`,表示密钥的比特长度。如果未指定,密钥的长度等于所选哈希函数的块大小。
    - 对于 `AES-CTR`、`AES-CBC` 或 `AES-GCM`,传递具有以下键的对象:
    <br/>
      `name`
      : 一个字符串,应根据所使用的算法设置为 `AES-CTR`、`AES-CBC` 或 `AES-GCM`。
    <br/>
      `length`
      : 一个 `number`,表示要生成的密钥的比特长度: `128`、`192` 或 `256`。
  <br/>
  `extractable`
  : 一个布尔值,指示是否可以导出密钥。
  <br/>
  `keyUsages`
  : 一个 `Array`,指示可以对派生密钥执行的操作。密钥用途必须被 `derivedKeyAlgorithm` 中设置的算法所允许。可能的值:
    <br/>
    `encrypt`
    : 用于加密消息的密钥。
    <br/>
    `decrypt`
    : 用于解密消息的密钥。
    <br/>
    `sign`
    : 用于签名消息的密钥。
    <br/>
    `verify`
    : 用于验证签名的密钥。
    <br/>
    `deriveKey`
    : 用于派生新密钥的密钥。
    <br/>
    `deriveBits`
    : 用于派生比特的密钥。
    <br/>
    `wrapKey`
    : 用于包装密钥的密钥。
    <br/>
    `unwrapKey`
    : 用于解包密钥的密钥。

`crypto.subtle.digest(algorithm, data)`
: 生成给定数据的摘要。接受要使用的摘要算法的标识符和要摘要的数据作为参数。返回一个 `Promise`,该 Promise 将使用摘要来完成。可能的值:
  <br/>
  `algorithm`
  : 一个字符串,定义要使用的哈希函数: `SHA-1` (不用于加密应用程序)、`SHA-256`、`SHA-384` 或 `SHA-512`。
  <br/>
  `data`
  : 一个 `ArrayBuffer`、`TypedArray` 或 `DataView`,包含要摘要的数据。

`crypto.subtle.exportKey(format, key)`
: 导出密钥:将密钥作为 `CryptoKey` 对象,并以外部可移植格式返回密钥(自 0.7.10 起)。如果 `format` 是 `jwk`,则 `Promise` 使用包含密钥的 JSON 对象来完成。否则,promise 使用包含密钥的 `ArrayBuffer` 来完成。可能的值:
  <br/>
  `format`
  : 一个字符串,描述应导出密钥的数据格式,可以是以下值:
    <br/>
    `raw`
    : 原始数据格式。

- 对于 `HMAC`,传递具有以下键的对象:
  > > > `name`
  > > > : 字符串,应设置为 `HMAC`。

  > > > `hash`
  > > > : 字符串,包含要使用的摘要函数的名称:可以是 `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。

  > > > `length`
  > > > : (可选)是一个 `number`,表示密钥的比特长度。如果未指定,密钥的长度等于所选哈希函数的块大小。
  > > - 对于 `AES-CTR`、`AES-CBC` 或 `AES-GCM`,传递具有以下键的对象:

  > >   `name`
  > >   : 字符串,应根据所使用的算法设置为 `AES-CTR`、`AES-CBC` 或 `AES-GCM`。

  > >   `length`
  > >   : 一个 `number`,表示要生成的密钥的比特长度:可以是 `128`、`192` 或 `256`。

  > `extractable`
  > : 布尔值,指示是否可以导出密钥。

  > `keyUsages`
  > : 一个 `Array`,指示派生密钥可以执行的操作。密钥用途必须被 `derivedKeyAlgorithm` 中设置的算法所允许。可能的值:
  >   <br/>
  >   `encrypt`
  >   : 用于加密消息的密钥。
  >   <br/>
  >   `decrypt`
  >   : 用于解密消息的密钥。
  >   <br/>
  >   `sign`
  >   : 用于签名消息的密钥。
  >   <br/>
  >   `verify`
  >   : 用于验证签名的密钥。
  >   <br/>
  >   `deriveKey`
  >   : 用于派生新密钥的密钥。
  >   <br/>
  >   `deriveBits`
  >   : 用于派生比特的密钥。
  >   <br/>
  >   `wrapKey`
  >   : 用于包装密钥的密钥。
  >   <br/>
  >   `unwrapKey`
  >   : 用于解包密钥的密钥。

`crypto.subtle.digest(algorithm, data)`
: 生成给定数据的摘要。接受要使用的摘要算法的标识符和要摘要的数据作为参数。返回一个 `Promise`,该 Promise 以摘要来兑现。可能的值:
  <br/>
  `algorithm`
  : 定义要使用的哈希函数的字符串:可以是 `SHA-1` (不用于加密应用)、`SHA-256`、`SHA-384` 或 `SHA-512`。
  <br/>
  `data`
  : 包含要摘要的数据的 `ArrayBuffer`、`TypedArray` 或 `DataView`。

`crypto.subtle.exportKey(format, key)`
: 导出密钥:接受一个密钥作为 `CryptoKey` 对象,并以外部可移植格式返回密钥(自 0.7.10 起)。如果 `format` 是 `jwk`,则 `Promise` 以包含密钥的 JSON 对象来兑现。否则,Promise 以包含密钥的 `ArrayBuffer` 来兑现。可能的值:
  <br/>
  `format`
  : 描述密钥应以何种数据格式导出的字符串,可以是以下值:
    <br/>
    `raw`
    : 原始数据格式。
    <br/>
    `pkcs8`
    : [PKCS #8](https://datatracker.ietf.org/doc/html/rfc5208) 格式。
    <br/>
    `spki`
    : [SubjectPublicKeyInfo](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1) 格式。
    <br/>
    `jwk`
    : [JSON Web Key](https://datatracker.ietf.org/doc/html/rfc7517) (JWK) 格式(自 0.7.10 起)。
  <br/>
  `key`
  : 包含要导出的密钥的 `CryptoKey`。

`crypto.subtle.generateKey(algorithm, extractable, usage)`
: 为对称算法生成新密钥或为公钥算法生成密钥对(自 0.7.10 起)。返回一个 `Promise`,该 Promise 以生成的密钥作为 `CryptoKey` 或 `CryptoKeyPair` 对象来兑现。可能的值:
  <br/>
  `algorithm`
  : 一个字典对象,定义要生成的密钥类型并提供额外的特定于算法的参数:
    <br/>
    - 对于 `RSASSA-PKCS1-v1_5`、`RSA-PSS` 或 `RSA-OAEP`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应根据所使用的算法设置为 `RSASSA-PKCS1-v1_5`、`RSA-PSS` 或 `RSA-OAEP`。
    <br/>
      `hash`
      : 字符串,表示要使用的 `digest` 函数的名称,可以是 `SHA-256`、`SHA-384` 或 `SHA-512`。
    - 对于 `ECDSA`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `ECDSA`。
    <br/>
      `namedCurve`
      : 字符串,表示要使用的椭圆曲线的名称,可以是 `P-256`、`P-384` 或 `P-521`。
    - 对于 `HMAC`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `HMAC`。
    <br/>
      `hash`
      : 字符串,表示要使用的 `digest` 函数的名称,可以是 `SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `length`
      : (可选)是一个数字,表示密钥的比特长度。如果省略,密钥的长度等于所选摘要函数生成的摘要的长度。
    - 对于 `AES-CTR`、`AES-CBC` 或 `AES-GCM`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象,其中 `ALGORITHM` 是算法的名称。
    - 对于 `ECDH`,传递具有以下键的对象(自 0.9.1 起):
    <br/>
      `name`
      : 字符串,应设置为 `ECDH`。
    <br/>
      `namedCurve`
      : 字符串,表示要使用的椭圆曲线的名称,可以是 `P-256`、`P-384` 或 `P-521`。
  <br/>
  `extractable`
  : 布尔值,指示是否可以导出密钥。
  <br/>
  `usage`
  : 一个 `array`,指示密钥的可能操作:
    <br/>
    `encrypt`
    : 用于加密消息的密钥。
    <br/>
    `decrypt`
    : 用于解密消息的密钥。
    <br/>
    `sign`
    : 用于签名消息的密钥。
    <br/>
    `verify`
    : 用于验证签名的密钥。
    <br/>
    `deriveKey`
    : 用于派生新密钥的密钥。
    <br/>
    `deriveBits`
    : 用于派生比特的密钥。
    <br/>
    `wrapKey`
    : 用于包装密钥的密钥。
    <br/>
    `unwrapKey`
    : 用于解包密钥的密钥。

`crypto.subtle.importKey(format, keyData, algorithm, extractable, keyUsages)`
: 导入密钥:接受外部可移植格式的密钥作为输入,并返回一个 `CryptoKey` 对象。返回一个 `Promise`,该 Promise 以导入的密钥作为 `CryptoKey` 对象来兑现。可能的值:
  <br/>
  `format`
  : 描述要导入的密钥的数据格式的字符串,可以是以下值:
    <br/>
    `raw`
    : 原始数据格式。
    <br/>
    `pkcs8`
    : [PKCS #8](https://datatracker.ietf.org/doc/html/rfc5208) 格式。
    <br/>
    `spki`
    : [SubjectPublicKeyInfo](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1) 格式。
    <br/>
    `jwk`
    : [JSON Web Key](https://datatracker.ietf.org/doc/html/rfc7517) (JWK) 格式(自 0.7.10 起)。
  <br/>
  `keyData`
  : 包含给定格式密钥的 `ArrayBuffer`、`TypedArray` 或 `DataView` 对象。
  <br/>
  `algorithm`
  : 定义要导入的密钥类型并提供额外的算法特定参数的字典对象:
    <br/>
    - 对于 `RSASSA-PKCS1-v1_5`、`RSA-PSS` 或 `RSA-OAEP`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应根据所使用的算法设置为 `RSASSA-PKCS1-v1_5`、`RSA-PSS` 或 `RSA-OAEP`。
    <br/>
      `hash`
      : 字符串,表示要使用的 `digest` 函数的名称,可以是 `SHA-1`、`SHA-256`、`SHA-384` 或 `SHA-512`。
    - 对于 `ECDSA`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `ECDSA`。
    <br/>
      `namedCurve`
      : 字符串,表示要使用的椭圆曲线的名称,可以是 `P-256`、`P-384` 或 `P-521`。
    - 对于 `HMAC`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `HMAC`。
    <br/>
      `hash`
      : 字符串,表示要使用的 `digest` 函数的名称,可以是 `SHA-256`、`SHA-384` 或 `SHA-512`。
    <br/>
      `length`
      : (可选)是一个数字,表示密钥的比特长度。如果省略,密钥的长度等于所选摘要函数生成的摘要的长度。
    - 对于 `AES-CTR`、`AES-CBC` 或 `AES-GCM`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象,其中 `ALGORITHM` 是算法的名称。
    - 对于 `PBKDF2`,传递 `PBKDF2` 字符串。
    - 对于 `HKDF`,传递 `HKDF` 字符串。
    - 对于 `ECDH`,传递具有以下键的对象(自 0.9.1 起):
    <br/>
      `name`
      : 字符串,应设置为 `ECDH`。
    <br/>
      `namedCurve`
      : 字符串,表示要使用的椭圆曲线的名称,可以是 `P-256`、`P-384` 或 `P-521`。
  <br/>
  `extractable`
  : 布尔值,指示是否可以导出密钥。
  <br/>
  `keyUsages`
  : 一个 `array`,指示密钥的可能操作:
    <br/>
    `encrypt`
    : 用于加密消息的密钥。
    <br/>
    `decrypt`
    : 用于解密消息的密钥。
    <br/>
    `sign`
    : 用于签名消息的密钥。
    <br/>
    `verify`
    : 用于验证签名的密钥。
    <br/>
    `deriveKey`
    : 用于派生新密钥的密钥。
    <br/>
    `deriveBits`
    : 用于派生比特的密钥。
    <br/>
    `wrapKey`
    : 用于包装密钥的密钥。
    <br/>
    `unwrapKey`
    : 用于解包密钥的密钥。

`crypto.subtle.sign(algorithm, key, data)`
: 返回 `signature` 作为 `Promise`,该 Promise 以包含签名的 `ArrayBuffer` 来兑现。可能的值:
  <br/>
  `algorithm`
  : 指定要使用的签名算法及其参数的字符串或对象:
    <br/>
    - 对于 `RSASSA-PKCS1-v1_5`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象。
    - 对于 `RSA-PSS`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `RSA-PSS`。
    <br/>
      `saltLength`
      : 长整型 `integer`,表示要使用的随机盐的长度(以字节为单位)。
    - 对于 `ECDSA`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `ECDSA`。
    <br/>
      `hash`
      : 要使用的摘要算法的标识符,可以是 `SHA-256`、`SHA-384` 或 `SHA-512`。
    - 对于 `HMAC`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象。
  <br/>
  `key`
  : 包含用于签名的密钥的 `CryptoKey` 对象。如果算法标识公钥密码系统,则这是私钥。
  <br/>
  `data`
  : 包含要签名的数据的 `ArrayBuffer`、`TypedArray` 或 `DataView` 对象。

`crypto.subtle.verify(algorithm, key, signature, data)`
: 验证数字签名;返回一个 `Promise`,该 Promise 以布尔值兑现:如果签名有效则为 `true`,否则为 `false`。可能的值:
  <br/>
  `algorithm`
  : 指定要使用的算法及其参数的字符串或对象:
    <br/>
    - 对于 `RSASSA-PKCS1-v1_5`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象。
    - 对于 `RSA-PSS`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `RSA-PSS`。
    <br/>
      `saltLength`
      : 长整型 `integer`,表示要使用的随机盐的长度(以字节为单位)。
    - 对于 `ECDSA`,传递具有以下键的对象:
    <br/>
      `name`
      : 字符串,应设置为 `ECDSA`。
    <br/>
      `hash`
      : 要使用的摘要算法的标识符,可以是 `SHA-256`、`SHA-384` 或 `SHA-512`。
    - 对于 `HMAC`,传递标识算法的字符串或形式为 ` *"name": "ALGORITHM"* ` 的对象。
  <br/>
  `key`
  : 包含用于验证的密钥的 `CryptoKey` 对象。对于对称算法,它是密钥;对于公钥系统,它是公钥。
  <br/>
  `signature`
  : 包含要验证的签名的 `ArrayBuffer`、`TypedArray` 或 `DataView`。
  <br/>
  `data`
  : 包含要验证其签名的数据的 `ArrayBuffer`、`TypedArray` 或 `DataView` 对象。

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

#### CryptoKey

- `CryptoKey.algorithm`
- `CryptoKey.extractable`
- `CryptoKey.type`
- `CryptoKey.usages`

`CryptoKey` 对象表示从 `SubtleCrypto` 方法之一获得的加密 `key`：`crypto.subtle.generateKey()`、`crypto.subtle.deriveKey()`、`crypto.subtle.importKey()`。

`CryptoKey.algorithm`
: 返回一个对象,描述此密钥可用于的算法以及任何相关的额外参数(自 0.8.0 起),只读。

`CryptoKey.extractable`
: 布尔值,如果密钥可以导出则为 `true` (自 0.8.0 起),只读。

`CryptoKey.type`
: 字符串值,指示对象表示的密钥类型,只读。可能的值:
  <br/>
  `secret`
  : 此密钥是用于对称算法的秘密密钥。
  <br/>
  `private`
  : 此密钥是非对称算法 `CryptoKeyPair` 的私钥部分。
  <br/>
  `public`
  : 此密钥是非对称算法 `CryptoKeyPair` 的公钥部分。

`CryptoKey.usages`
: 字符串数组,指示此密钥可用于什么用途(自 0.8.0 起),只读。可能的数组值:
  <br/>
  `encrypt`
  : 用于加密消息的密钥。
  <br/>
  `decrypt`
  : 用于解密消息的密钥。
  <br/>
  `sign`
  : 用于签名消息的密钥。
  <br/>
  `verify`
  : 用于验证签名的密钥。
  <br/>
  `deriveKey`
  : 用于派生新密钥的密钥。
  <br/>
  `deriveBits`
  : 用于派生比特的密钥。

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

#### CryptoKeyPair

- `CryptoKeyPair.privateKey`
- `CryptoKeyPair.publicKey`

`CryptoKeyPair` 是 WebCrypto API 的字典对象,表示非对称密钥对。

`CryptoKeyPair.privateKey`
: 表示私钥的 `CryptoKey` 对象。

`CryptoKeyPair.publicKey`
: 表示公钥的 `CryptoKey` 对象。

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

### njs

- `njs.version`
- `njs.version_number`
- `njs.dump()`
- `njs.memoryStats`
- `njs.on()`

`njs` 对象是表示当前 VM 实例的全局对象(自 0.2.0 起)。

`njs.version`
: 返回包含当前 NJS 版本的字符串(例如,"0.7.4")。

`njs.version_number`
: 返回包含当前 NJS 版本的数字。例如,"0.7.4" 返回为 `0x000704` (自 0.7.4 起)。

`njs.dump(value)`
: 返回值的美化打印字符串表示。

`njs.memoryStats`
: 包含当前 VM 实例内存统计信息的对象(自 0.7.8 起)。
  <br/>
  `size`
  : NJS 内存池从操作系统申请的内存量(以字节为单位)。

`njs.on(event, callback)`
: 为指定的 VM 事件注册回调(自 0.5.2 起)。事件可以是以下字符串之一:
  <br/>
  `exit`
  : 在 VM 销毁之前调用。回调不带参数调用。

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

### process

- `process.argv`
- `process.env`
- `process.kill()`
- `process.pid`
- `process.ppid`

`process` 对象是提供有关当前进程信息的全局对象(0.3.3)。

`process.argv`
: 返回包含启动当前进程时传递的命令行参数的数组。

`process.env`
: 返回包含用户环境的对象。
  <br/>
  #### NOTE
  默认情况下,Angie 会删除从其父进程继承的所有环境变量,但 TZ 变量除外。使用 `env` 指令来保留一些继承的变量。

`process.kill(pid, number | string)`
: 向由 `pid` 标识的进程发送信号。信号名称是数字或字符串,例如 `SIGINT` 或 `SIGHUP`。有关更多信息,请参阅 [kill(2)](https://man7.org/linux/man-pages/man2/kill.2.html)。

`process.pid`
: 返回当前进程的 PID。

`process.ppid`
: 返回当前父进程的 PID。

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

### String

默认情况下,NJS 中的所有字符串都是 Unicode 字符串。它们对应于包含 Unicode 字符的 ECMAScript 字符串。在 0.8.0 之前,还支持字节字符串。

<a id="byte-strings-removed"></a>

#### 字节字符串(已移除)

#### NOTE
自 0.8.0 起,已移除对字节字符串和字节字符串方法的支持。在处理字节序列时,应使用 [Buffer](#njs-buffer) 对象和 Buffer 属性,例如 `r.requestBuffer`、`r.rawVariables`。

字节字符串包含字节序列,用于将 Unicode 字符串序列化为外部数据以及从外部源反序列化。例如,:samp:toUTF8() 方法使用 UTF-8 编码将 Unicode 字符串序列化为字节字符串。`toBytes()` 方法将代码点最多为 255 的 Unicode 字符串序列化为字节字符串;否则返回 `null`。

以下方法已过时并在 0.8.0 中移除:

- `String.bytesFrom()` (在 0.8.0 中移除,使用 `Buffer.from()`)
- `String.prototype.fromBytes()` (在 0.8.0 中移除)
- `String.prototype.fromUTF8()` (在 0.8.0 中移除,使用 `TextDecoder`)
- `String.prototype.toBytes()` (在 0.8.0 中移除)
- `String.prototype.toString()` 带编码(在 0.8.0 中移除)
- `String.prototype.toUTF8()` (在 0.8.0 中移除,使用 `TextEncoder`)

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

## Web API

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

### TextDecoder

- `TextDecoder()`
- `TextDecoder.prototype.encoding`
- `TextDecoder.prototype.fatal`
- `TextDecoder.prototype.ignoreBOM`
- `TextDecoder.prototype.decode()`

`TextDecoder` 从字节流生成代码点流(0.4.3)。

`TextDecoder([[encoding], options])`
: 为指定的 `encoding` 创建新的 `TextDecoder` 对象;目前仅支持 UTF-8。`options` 是具有以下属性的 `TextDecoderOptions` 字典:
  <br/>
  `fatal`
  : 布尔标志,指示当发现编码错误时 `TextDecoder.decode()` 是否必须抛出 `TypeError` 异常,默认为 `false`。

`TextDecoder.prototype.encoding`
: 返回包含 `TextDecoder()` 使用的编码名称的字符串,只读。

`TextDecoder.prototype.fatal`
: 布尔标志,如果错误模式是致命的则为 `true`,只读。

`TextDecoder.prototype.ignoreBOM`
: 布尔标志,如果忽略字节顺序标记则为 `true`,只读。

`TextDecoder.prototype.decode(buffer, [options])`
: 返回包含由 `TextDecoder()` 从 `buffer` 解码的文本的字符串。缓冲区可以是 `ArrayBuffer`。`options` 是具有以下属性的 `TextDecodeOptions` 字典:
  <br/>
  `stream`
  : 布尔标志,指示后续调用 `decode()` 时是否会有额外数据:如果分块处理数据则为 `true`,如果是最后一块或数据未分块则为 `false`。默认为 `false`。
  <br/>
  示例:
  <br/>
  ```javascript
  >> (new TextDecoder()).decode(new Uint8Array([206,177,206,178]))
  αβ
  ```

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

### TextEncoder

- `TextEncoder()`
- `TextEncoder.prototype.encode()`
- `TextEncoder.prototype.encodeInto()`

`TextEncoder` 对象从代码点流生成 UTF-8 编码的字节流(0.4.3)。

`TextEncoder()`
: 返回新构造的 `TextEncoder`,它将生成 UTF-8 编码的字节流。

`TextEncoder.prototype.encode(string)`
: 将 `string` 编码为包含 UTF-8 编码文本的 `Uint8Array`。

`TextEncoder.prototype.encodeInto(string, uint8Array)`
: 将 `string` 编码为 UTF-8,将结果放入目标 `Uint8Array`,并返回显示编码进度的字典对象。字典对象包含两个成员:
  <br/>
  `read`
  : 从源 `string` 转换为 UTF-8 的 UTF-16 代码单元数。
  <br/>
  `written`
  : 目标 `Uint8Array` 中修改的字节数。

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

## 定时器

- `clearTimeout()`
- `setTimeout()`

`clearTimeout(timeout)`
: 取消由 `setTimeout()` 创建的 `timeout` 对象。

`setTimeout(function, milliseconds[, argument1, argumentN])`
: 在指定的 `milliseconds` 毫秒数后调用 `function`。可以向指定的函数传递一个或多个可选 `arguments`。返回 `timeout` 对象。
  <br/>
  示例:
  <br/>
  ```javascript
  function handler(v)
  {
      // ...
  }
  <br/>
  t = setTimeout(handler, 12);
  <br/>
  // ...
  <br/>
  clearTimeout(t);
  ```

<a id="njs-global-functions"></a>

### 全局函数

- `atob()`
- `btoa()`

`atob(encodedData)`
: 解码使用 `Base64` 编码的数据字符串。`encodedData` 参数是包含 Base64 编码数据的二进制字符串。返回包含从 `encodedData` 解码的数据的字符串。
  <br/>
  类似的 `btoa()` 方法可用于编码和传输可能导致通信问题的数据,然后传输它并使用 `atob()` 方法再次解码数据。例如,您可以编码、传输和解码控制字符,如 ASCII 值 `0` 到 `31`。
  <br/>
  示例:
  <br/>
  ```javascript
  const encodedData = btoa("text to encode"); // 编码字符串
  const decodedData = atob(encodedData); // 解码字符串
  ```

`btoa(stringToEncode)`
: 从二进制字符串创建 Base64 编码的 ASCII 字符串。`stringToEncode` 参数是要编码的二进制字符串。返回包含 `stringToEncode` 的 Base64 表示的 ASCII 字符串。
  <br/>
  该方法可用于编码可能导致通信问题的数据,传输它,然后使用 `atob()` 方法再次解码数据。例如,您可以编码控制字符,如 ASCII 值 `0` 到 `31`。
  <br/>
  示例:
  <br/>
  ```javascript
  const encodedData = btoa("text to encode"); // 编码字符串
  const decodedData = atob(encodedData); // 解码字符串
  ```

<a id="njs-builtin-modules"></a>

## 内置模块

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

### Buffer

`Buffer` 对象是处理二进制数据的 Node.js 兼容方式。由于文件内容过于庞大,本节仅限于 Buffer 方法的完整列表。

- `Buffer.alloc()`
- `Buffer.allocUnsafe()`
- `Buffer.byteLength()`
- `Buffer.compare()`
- `Buffer.concat()`
- `Buffer.from(array)`
- `Buffer.from(arrayBuffer)`
- `Buffer.from(buffer)`
- `Buffer.from(object)`
- `Buffer.from(string)`
- `Buffer.isBuffer()`
- `Buffer.isEncoding()`
- `buffer[]`
- `buf.buffer`
- `buf.byteOffset`
- `buf.compare()`
- `buf.copy()`
- `buf.equals()`
- `buf.fill()`
- `buf.includes()`
- `buf.indexOf()`
- `buf.lastIndexOf()`
- `buf.length`
- `buf.readIntBE()`
- `buf.readIntLE()`
- `buf.readUIntBE()`
- `buf.readUIntLE()`
- `buf.readDoubleBE()`
- `buf.readDoubleLE()`
- `buf.readFloatBE()`
- `buf.readFloatLE()`
- `buf.subarray()`
- `buf.slice()`
- `buf.swap16()`
- `buf.swap32()`
- `buf.swap64()`
- `buf.toJSON()`
- `buf.toString()`
- `buf.write()`
- `buf.writeIntBE()`
- `buf.writeIntLE()`
- `buf.writeUIntBE()`
- `buf.writeUIntLE()`
- `buf.writeDoubleBE()`
- `buf.writeDoubleLE()`
- `buf.writeFloatBE()`
- `buf.writeFloatLE()`

有关 Buffer 方法的详细文档,请参阅 [Node.js Buffer 文档](https://nodejs.org/api/buffer.html)。

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

### Crypto

Crypto 模块提供加密功能支持。Crypto 模块对象使用 `import crypto from 'crypto'` 导入。

#### NOTE
自 0.7.0 起,扩展的 crypto API 可作为全局 [crypto](#njs-builtin-crypto) 对象使用。

- `crypto.createHash()`
- `crypto.createHmac()`

`crypto.createHash(algorithm)`
: 创建并返回一个 Hash 对象,可使用给定的 `algorithm` 生成哈希摘要。算法可以是 `md5`、`sha1` 和 `sha256`。

`crypto.createHmac(algorithm, secret key)`
: 创建并返回一个 HMAC 对象,使用给定的 `algorithm` 和 `secret key`。算法可以是 `md5`、`sha1` 和 `sha256`。

<a id="hash"></a>

#### Hash

- `hash.update()`
- `hash.digest()`

`hash.update(data)`
: 使用给定的 `data` 更新哈希内容。

`hash.digest([encoding])`
: 计算使用 `hash.update()` 传递的所有数据的摘要。编码可以是 `hex`、`base64` 和 `base64url`。如果未提供编码,则返回 Buffer 对象(0.4.4)。
  <br/>
  #### NOTE
  在 0.4.4 版本之前,返回的是字节字符串而不是 Buffer 对象。

`hash.copy()`
: 复制哈希的当前状态(自 0.7.12 起)。

示例:

```javascript
import crypto from 'crypto';

crypto.createHash('sha1').update('A').update('B').digest('base64url');
/* BtlFlCqiamG-GMPiK_GbvKjdK10 */
```

<a id="hmac"></a>

#### HMAC

- `hmac.update()`
- `hmac.digest()`

`hmac.update(data)`
: 使用给定的 `data` 更新 HMAC 内容。

`hmac.digest([encoding])`
: 计算使用 `hmac.update()` 传递的所有数据的 HMAC 摘要。编码可以是 `hex`、`base64` 和 `base64url`。如果未提供编码,则返回 Buffer 对象(0.4.4)。
  <br/>
  #### NOTE
  在 0.4.4 版本之前,返回的是字节字符串而不是 Buffer 对象。

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

### fs

`fs` 模块提供文件系统操作。模块对象使用 `import fs from 'fs'` 导入。

- `fs.accessSync()`
- `fs.appendFileSync()`
- `fs.mkdirSync()`
- `fs.readdirSync()`
- `fs.readFileSync()`
- `fs.realpathSync()`
- `fs.renameSync()`
- `fs.rmdirSync()`
- `fs.symlinkSync()`
- `fs.unlinkSync()`
- `fs.writeFileSync()`
- `fs.promises.readFile()`
- `fs.promises.appendFile()`
- `fs.promises.writeFile()`
- `fs.promises.readdir()`
- `fs.promises.mkdir()`
- `fs.promises.rmdir()`
- `fs.promises.rename()`
- `fs.promises.unlink()`
- `fs.promises.symlink()`
- `fs.promises.access()`
- `fs.promises.realpath()`

有关 fs 方法的详细文档,请参阅 [Node.js fs 文档](https://nodejs.org/api/fs.html)。

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

### Query String

Query String 模块提供解析和格式化 URL 查询字符串的方法。模块对象使用 `import qs from 'querystring'` 导入。

- `querystring.decode()`
- `querystring.encode()`
- `querystring.escape()`
- `querystring.parse()`
- `querystring.stringify()`
- `querystring.unescape()`

`querystring.decode()`
: `querystring.parse()` 的别名。

`querystring.encode()`
: `querystring.stringify()` 的别名。

`querystring.escape(string)`
: 以针对 URL 查询字符串要求优化的方式对 `string` 执行 URL 百分号编码。该方法由 `querystring.stringify()` 使用,不应直接使用。

`querystring.parse(string[, separator[, equal[, options]]])`
: 将 `string` 解析为 URL 查询字符串并返回一个对象。可选的 `separator` 参数(默认值: `&`)指定用于分隔键值对的子字符串。可选的 `equal` 参数(默认值: `=`)指定用于分隔键和值的子字符串。可选的 `options` 参数是一个对象,可能包含以下属性:
  <br/>
  `decodeURIComponent`
  : 解码查询字符串中百分号编码字符时使用的函数,默认值: `querystring.unescape()`。
  <br/>
  `maxKeys`
  : 要解析的最大键数,默认值: `1000`。值 `0` 会移除对键计数的限制。
  <br/>
  示例:
  <br/>
  ```javascript
  >> qs.parse('foo=bar&abc=xyz&abc=123')
  {
      foo: 'bar',
      abc: ['xyz', '123']
  }
  ```

`querystring.stringify(object[, separator[, equal[, options]]])`
: 通过迭代 `object` 的自有属性从中生成 URL 查询字符串。可选的 `separator` 参数(默认值: `&`)指定用于分隔键值对的子字符串。可选的 `equal` 参数(默认值: `=`)指定用于分隔键和值的子字符串。可选的 `options` 参数是一个对象,可能包含以下属性:
  <br/>
  `encodeURIComponent`
  : 将查询字符串中的 URL 不安全字符转换为百分号编码时使用的函数,默认值: `querystring.escape()`。
  <br/>
  示例:
  <br/>
  ```javascript
  >> qs.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' })
  'foo=bar&baz=qux&baz=quux&corge='
  ```

`querystring.unescape(string)`
: 对 `string` 中的 URL 百分号编码字符执行解码。该方法由 `querystring.parse()` 使用,不应直接使用。

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

### XML

- `xml.parse()`
- `xml.c14n()`
- `xml.exclusiveC14n()`
- `xml.serialize()`
- `xml.serializeToString()`
- `XMLDoc`
- `XMLNode`
- `XMLAttr`

XML 模块允许处理 XML 文档(自 0.7.10 起)。XML 模块对象使用 `import xml from 'xml'` 导入。

示例:

```javascript
import xml from 'xml';

let data = `<note><to b="bar" a= "foo" >Tove</to><from>Jani</from></note>`;
let doc = xml.parse(data);

console.log(doc.note.to.$text) /* 'Tove' */
console.log(doc.note.to.$attr$b) /* 'bar' */
console.log(doc.note.$tags[1].$text) /* 'Jani' */

let dec = new TextDecoder();
let c14n = dec.decode(xml.exclusiveC14n(doc.note));
console.log(c14n) /* '<note><to a="foo" b="bar">Tove</to><from>Jani</from></note>' */

c14n = dec.decode(xml.exclusiveC14n(doc.note.to));
console.log(c14n) /* '<to a="foo" b="bar">Tove</to>' */

c14n = dec.decode(xml.exclusiveC14n(doc.note, doc.note.to /* excluding 'to' */));
console.log(c14n) /* '<note><from>Jani</from></note>' */
```

`parse(string | Buffer)`
: 解析字符串或 Buffer 中的 XML 文档;返回一个表示已解析 XML 文档的 `XMLDoc` 包装对象。

`c14n(root_node[, excluding_node])`
: 根据 [规范 XML 版本 1.1](https://www.w3.org/TR/xml-c14n) 规范化 `root_node` 及其子节点。`root_node` 可以是围绕 XML 结构的 `XMLNode` 或 `XMLDoc` 包装对象。返回包含规范化输出的 Buffer 对象。
  <br/>
  `excluding_node`
  : 允许从输出中省略文档的一部分。

`exclusiveC14n(root_node[, excluding_node[, withComments[,prefix_list]]])`
: 根据 [独占 XML 规范化版本 1.0](https://www.w3.org/TR/xml-exc-c14n/) 规范化 `root_node` 及其子节点。
  <br/>
  `root_node`
  : 围绕 XML 结构的 `XMLNode` 或 `XMLDoc` 包装对象。
  <br/>
  `excluding_node`
  : 允许从输出中省略与该节点及其子节点对应的文档部分。
  <br/>
  `withComments`
  : 布尔值,默认为 `false`。如果为 `true`,规范化对应于 [带注释的独占 XML 规范化版本 1.0](http://www.w3.org/2001/10/xml-exc-c14n#WithComments)。返回包含规范化输出的 Buffer 对象。
  <br/>
  `prefix_list`
  : 可选字符串,包含以空格分隔的命名空间前缀,这些命名空间也应包含在输出中。

`serialize()`
: 与 `xml.c14n()` 相同(自 0.7.11 起)。

`serializeToString()`
: 与 `xml.c14n()` 相同,但以 `string` 形式返回结果(自 0.7.11 起)。

`XMLDoc`
: 围绕 XML 结构的 XMLDoc 包装对象,文档的根节点。
  <br/>
  > `doc.$root`
  > : 按名称获取文档的根节点,如果不存在则为 undefined。
  <br/>
  > `doc.abc`
  > : 名为 `abc` 的第一个根标签,作为 `XMLNode` 包装对象。

`XMLNode`
: 围绕 XML 标签节点的 XMLNode 包装对象。
  <br/>
  > `node.abc`
  > : 与 `node.$tag$abc` 相同。
  <br/>
  > `node.$attr$abc`
  > : 节点的 `abc` 属性值,自 0.7.11 起可写。
  <br/>
  > `node.$attr$abc=xyz`
  > : 与 `node.setAttribute('abc', xyz)` 相同(自 0.7.11 起)。
  <br/>
  > `node.$attrs`
  > : 节点所有属性的 `XMLAttr` 包装对象。
  <br/>
  > `node.$name`
  > : 节点的名称。
  <br/>
  > `node.$ns`
  > : 节点的命名空间。
  <br/>
  > `node.$parent`
  > : 当前节点的父节点。
  <br/>
  > `node.$tag$abc`
  > : 节点名为 `abc` 的第一个子标签,自 0.7.11 起可写。
  <br/>
  > `node.$tags`
  > : 所有子标签的数组。
  <br/>
  > `node.$tags = [node1, node2, ...]`
  > : 与 `node.removeChildren()`; `node.addChild(node1)`; `node.addChild(node2)` 相同(自 0.7.11 起)。
  <br/>
  > `node.$tags$abc`
  > : 节点所有名为 `abc` 的子标签,自 0.7.11 起可写。
  <br/>
  > `node.$text`
  > : 节点的内容,自 0.7.11 起可写。
  <br/>
  > `node.$text = 'abc'`
  > : 与 `node.setText('abc')` 相同(自 0.7.11 起)。
  <br/>
  > `node.addChild(nd)`
  > : 将 XMLNode 作为子节点添加到该节点(自 0.7.11 起)。`nd` 在添加到节点之前会被递归复制。
  <br/>
  > `node.removeAllAttributes()`
  > : 删除节点的所有属性(自 0.7.11 起)。
  <br/>
  > `node.removeAttribute(attr_name)`
  > : 删除名为 `attr_name` 的属性(自 0.7.11 起)。
  <br/>
  > `node.removeChildren(tag_name)`
  > : 删除所有名为 `tag_name` 的子标签(自 0.7.11 起)。如果 `tag_name` 不存在,则删除所有子标签。
  <br/>
  > `node.removeText()`
  > : 删除节点的文本值(0.7.11)。
  <br/>
  > `node.setAttribute(attr_name, value)`
  > : 为 `attr_name` 设置值(自 0.7.11 起)。当值为 `null` 时,删除名为 `attr_name` 的属性。
  <br/>
  > `node.setText(value)`
  > : 为节点设置文本值(自 0.7.11 起)。当值为 `null` 时,删除节点的文本。

`XMLAttr`
: 围绕 XML 节点属性的 XMLAttrs 包装对象。
  <br/>
  > `attr.abc`
  > : `abc` 的属性值。

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

### zlib

`zlib` 模块(0.5.2)使用 zlib 提供压缩和解压缩功能。模块对象使用 `import zlib from 'zlib'` 导入。

- `zlib.constants`
- `zlib.deflateRawSync()`
- `zlib.deflateSync()`
- `zlib.inflateRawSync()`
- `zlib.inflateSync()`

`zlib.constants`
: 返回 zlib 常量字典。

`zlib.deflateRawSync(data[, options])`
: 使用 Deflate 算法压缩 `data`,不包含 zlib 头。

`zlib.deflateSync(data[, options])`
: 使用 Deflate 算法压缩 `data`。

`zlib.inflateRawSync(data[, options])`
: 使用 Deflate 算法解压缩 `data`,不包含 zlib 头。

`zlib.inflateSync(data[, options])`
: 使用 Deflate 算法解压缩 `data`。

`options` 参数是一个对象,可能包含以下属性:

`level`
: 压缩级别(默认值: `zlib.constants.Z_DEFAULT_COMPRESSION`)。

`memLevel`
: 指定应为压缩状态分配多少内存(默认值: `zlib.constants.Z_DEFAULT_MEMLEVEL`)。

`strategy`
: 调整压缩算法(默认值: `zlib.constants.Z_DEFAULT_STRATEGY`)。

`windowBits`
: 设置窗口大小(默认值: `zlib.constants.Z_DEFAULT_WINDOWBITS`)。

`dictionary`
: 包含预定义压缩字典的 Buffer。

`info`
: 布尔值,如果为 `true`,返回包含 buffer 和 engine 的对象。

`chunkSize`
: 压缩的块大小(默认值: `zlib.constants.Z_DEFAULT_CHUNK`)。

示例:

```javascript
import zlib from 'zlib';

const deflated = zlib.deflateSync('Hello World!');
const inflated = zlib.inflateSync(deflated);

console.log(inflated.toString()); // 'Hello World!'
```
