Node.js 的 Http/2 模块

 2018年10月27日    113     声明


http2模块是自Node.jsv8.4.0起添加的一个核心模块,它主要提供了对HTTP/2协议的实现。

  1. 核心API
  2. 兼容API
  3. HTTP/2 性能指标收集

http2模块中包括两部分API:核心API(Core API)、兼容API(Compatibility API)。其中,核心API是全心实现的一个低级接口,专门用于支持 HTTP/2 协议功能,它与现有的HTTP/1模块的API不兼容;而兼容API则旨在提供与现在HTTP/1模块类似的API,从而可以开发同时支持 HTTP/1 与 HTTP/2 的应用。

引用http2模块:

const http2 = require('http2');


1. 核心API

http2模块的“核心API”相比于http模块,其API更加对称。如,大多数事件,像'error''connect''stream'即可以通过客户端代码发出,又可以通过服务端代码发出。

1.1 使用示例

服务端示例

可以像如下这样使用服务端“核心API”。在以下示例中,使用http2.createSecureServer()创建了加密的 HTTP/2 服务器,因为目前还没有支持不加密的 HTTP/2

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem')
});
server.on('error', (err) => console.error(err));

server.on('stream', (stream, headers) => {
  // stream 是一个双工流
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.end('<h1>Hello World</h1>');
});

server.listen(8443);

生成上例中使用的私钥及证书:

openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
  -keyout localhost-privkey.pem -out localhost-cert.pem


客户端示例

使用http2模块的客户端API:

const http2 = require('http2');
const fs = require('fs');
const client = http2.connect('https://localhost:8443', {
  ca: fs.readFileSync('localhost-cert.pem')
});
client.on('error', (err) => console.error(err));

const req = client.request({ ':path': '/' });

req.on('response', (headers, flags) => {
  for (const name in headers) {
    console.log(`${name}: ${headers[name]}`);
  }
});

req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => {
  console.log(`\n${data}`);
  client.close();
});
req.end();

运行服端后,可以在浏览器输入https://127.0.0.1:8443查看运行效果,也可以通过以上客户端访问。


1.2 Class: Http2Session

http2.Http2Session类的实例是 HTTP/2 客户端和服务器之间的一个活跃通信会话。这个类的实例不是由用户代码直接构造。

每个Http2Session实例所表现的行为略有不同,这取决于其运行于服务端还是客户端,可以通过http2session.type属性来确定Http2Session的运行环境。在服务端,用户代码很少会直接使用Http2Session对象,大多数操作是通过与<Http2ServerHttp2Stream对象的交互来完成。


1.2.1 Http2Session与Socket

每个Http2Session实例在创建时都会与一个net.Sockettls.TLSSocket相关联。当SocketHttp2Session被销毁时,两者都将被销毁。

由于 HTTP/2 协议强制要求的指定序列化及处理要求,不建议用户代码从Http2Session所绑定的Socket实例读取或写入数据。这样会使 HTTP/2 会话进入不确定状态,从而导致会话和套接字变得不可用。

一旦Socket绑定到Http2Session,用户代码应该仅使用Http2Session的API。


1.2.2 Http2Session中的事件

Event: 'close'

'close'事件会在Http2Session销毁时发送一次,其回调函数中没有任何参数。


Event: 'connect'

'connect'事件会成功连接远程端(服务端或客户端)并可以开始通讯时发出。用户代码通常不会直接监听这个事件。

其回调函数参数如下:

  • session <Http2Session>
  • socket <net.Socket>


Event: 'error'

Http2Session处理期间发生错误时会发出'error'事件。

其回调函数参数如下:

  • error <Error>


Event: 'frameError'

在尝试发送帧发生错误时会发出'frameError'事件。如果无法发送的帧与特定的Http2Stream相关联,则会尝试在Http2Stream上发出'frameError'事件

如果'frameError'事件与流相关联,则流将在'frameError'事件之后立即关闭并销毁。如果事件未与流关联,则Http2Session会在'frameError'事件后立即关闭。

其回调函数参数如下:

  • type <integer>帧的类型
  • code <integer>错误码
  • id <integer>流ID(如果帧没有与流关联,则为0)


Event: 'goaway'

当收到GOAWAY帧时会发出'goaway'事件。发出'goaway'事件时,Http2Session实例将自动关闭。

'goaway'事件回调函数参数如下:

  • errorCode <number>GOAWAY帧中指定的 HTTP/2 错误码
  • lastStreamID <number>远程对等方成功处理的最后一个流的ID(如果未指定ID,则为0)。
  • opaqueData <Buffer>GOAWAY帧中包含其他不透明数据,则将传递包含该数据的Buffer实例。


Event: 'localSettings'

当收到SETTINGS帧时,会发出'localSettings'事件。使用http2session.settings()提交新设置时,修改后的设置在发出'localSettings'事件后才会生效。

session.settings({ enablePush: false });

session.on('localSettings', (settings) => {
  /* 使用新设置 */
});

'localSettings'事件回调函数参数如下:


Event: 'remoteSettings'

当从所连接的对等方接收到新的SETTINGS帧时,将发出'remoteSettings'事件。

session.on('remoteSettings', (settings) => {
  /* 使用新设置 */
});

'remoteSettings'事件回调函数参数如下:


Event: 'stream'

当新的Http2Stream创建后,会发出'stream'事件。

const http2 = require('http2');
session.on('stream', (stream, headers, flags) => {
  const method = headers[':method'];
  const path = headers[':path'];
  // ...
  stream.respond({
    ':status': 200,
    'content-type': 'text/plain'
  });
  stream.write('hello ');
  stream.end('world');
});

在服务器端,用户代码通常不会直接监听这事件,而是为替代http.createServer()http2.createSecureServer()所返回的net.Servertls.Server实例发出的'stream'事件注册处理程序。分别如下所示:

const http2 = require('http2');

// Create an unencrypted HTTP/2 server
const server = http2.createServer();

server.on('stream', (stream, headers) => {
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.on('error', (error) => console.error(error));
  stream.end('<h1>Hello World</h1>');
});

server.listen(80);

即使 HTTP/2 流和网络套接字不是1:1的对应关系,网络错误也会破坏每个单独的流,所以必须在流级别处理(如上所示)。

'stream'事件回调函数参数如下:

  • stream <Http2Stream>所引用的流
  • headers <HTTP/2 Headers Object>头描述对象
  • flags <number>相关的数字标志
  • rawHeaders <Array>一个包含原始头名称的数组,其后为各自的值。


Event: 'timeout'

http2session.setTimeout()方法设置Http2Session的超时时间后,如果在所配置的毫秒数后Http2Session没有活动,则会发出'timeout'事件。

session.setTimeout(2000);
session.on('timeout', () => { /* .. */ });


1.2.3 http2session.alpnProtocol 属性

  • <string> | <undefined>

Http2Session尚未连接到套接字,则值为undefined,如果Http2Session未连接到TLSSocket,则为h2c,或者将返回已连接的TLSSocket自己的alpnProtocol属性的值。


1.2.4 http2session.close([callback])

  • callback | <Function>

优雅地关闭Http2Session,允许任何已有的流自己完成处理并阻止创建新的Http2Session实例。 关闭后,如果没有打开的Http2Session例,可能会调用http2session.destroy()

如果指定回调函数,则会被注册为'close'事件的处理程序。


1.2.5 http2session.closed 属性

  • <boolean>

当为true时表示Http2Session已关闭,其它情况为false


1.2.6 http2session.connecting 属性

  • <boolean>

当为true时表示Http2Session仍为连接状态,在收到'connect'事件前和/或调用http2.connect回调前为false


1.2.7 http2session.destroy([error][, code])

  • error<Error>如果Http2Session因错误被销毁,则为Error对象。
  • code<Number>要在最终GOAWAY帧中发送的 HTTP/2 错误代码。如果未指定且未定义错误,则默认为INTERNAL_ERROR,否则默认为NO_ERROR

立即中止Http2Session和相关的net.Sockettls.TLSSocket

被销毁后,Http2Session会发出'close'事件。如果error不是未定义,则会在'close'事件之前发出'error'事件。

如果有任何与Http2Session相关联的已打开的Http2Stream,其也会将被销毁。


1.2.8 http2session.destroyed 属性

  • <boolean>

如果为trueHttp2Session实例已被销毁且不能再使用,否则为false。


1.2.9 http2session.encrypted 属性

  • <boolean> | <undefined>

如果Http2Session会话套接字尚未连接,则值为undefined;如果已与TLSSocket连接,则为true;如果连接到任何其他类型的套接字或流,则为false


1.2.10 http2session.goaway([code[, lastStreamID[, opaqueData]]])

  • code<Number>HTTP/2错误码。
  • lastStreamID<Number>最后处理的Http2Stream的数字ID。
  • opaqueData<Buffer> | <TypedArray> | <DataView>TypedArrayDataView实例,包含要在GOAWAY帧中携带的其他数据。

在不关闭Http2Session的情况下将GOAWAY帧传输到所连接的对等方。


1.2.11 http2session.localSettings 属性

一个无原型的对象,描述了这个Http2Session的当前本地设置。


1.2.12 http2session.originSet 属性

  • <string> | <undefined>

如果Http2Session已连接到TLSSocket,则originSet属性将返回一个原始Array


1.2.13 http2session.pendingSettingsAck 属性

  • <boolean>

指示Http2Session当前是否正在等待发送的SETTINGS帧确认。 调用http2session.settings()方法后为true;一旦所有发送的SETTINGS帧都被确认,则为false


1.2.14 http2session.ping([payload, ]callback)

  • payload<Buffer> | <TypedArray> | <DataView>可选,ping负载。
  • callback<Function>必须
  • Returns<boolean>如果PING被发送,将返回true,否则返回false

PING帧发送到所连接的 HTTP/2对等方。

未完成(未确认)ping的最大数量由maxOutstandingPings配置选项确定。 默认最大值为10。

如果提供payload,则有效负载必须是包含8个字节数据的<Buffer>、<TypedArray>或<DataView>,这些数据将与PING一起传输并通过ping确认返回。

callback会包含三个参数:error-如果PING成功确认将为nullduration-报告自发送ping以及收到确认后所经过的毫秒数;Buffer-包含8-byte的PING负载。

session.ping(Buffer.from('abcdefgh'), (err, duration, payload) => {
  if (!err) {
    console.log(`Ping acknowledged in ${duration} milliseconds`);
    console.log(`With payload '${payload.toString()}'`);
  }
});

如果未指定payload参数,则默认有效负载将为标记PING持续时间开始的64位时间戳(little endian)。


1.2.15 http2session.ref()

Http2Session实例的底层net.Socket上调用ref()


1.2.16 http2session.remoteSettings 属性

一个无原型对象,描述Http2Session的当前远程设置。远程设置由所连接的 HTTP/2 对等方进行设置。


1.2.17 http2session.setTimeout(msecs, callback)

  • msecs<number>
  • callback<Function>

设置在msecs毫秒后Http2Session上没有活动时调用的回调函数。所指定的回调会在'timeout'事件中注册为监听函数。


1.2.18 http2session.socket 属性

  • <net.Socket> | <tls.TLSSocket>

返回net.Socket(或tls.TLSSocket)的Proxy对象,但可用方法限制为可用于 HTTP/2 的安全方法。

destroyemitendpausereadresumewrite将使用触发错误代码ERR_HTTP2_NO_SOCKET_MANIPULATION

会在Http2Session上调用setTimeout方法。所有其他交互将直接路由到套接字。


1.2.19 http2session.state 属性

Http2Session的当前各种状态信息,用以下包含以下属性的对象表示

  • <Object>
    • effectiveLocalWindowSize <number> Http2Session当前本地(接收)流控制窗口大小
    • effectiveRecvDataLength <number> 自上次流控制WINDOW_UPDATE以来收到的当前字节数
    • nextStreamID <number> 数字标识符,用于 下次由Http2Session创建一个新的Http2Stream.
    • localWindowSize <number> The number of bytes that the remote peer can send without receiving a WINDOW_UPDATE.
    • lastProcStreamID <number> Http2Stream的数字ID,可能是最近收到的HEADERSDATA
    • remoteWindowSize <number> 此Http2Session 的字节数, 可在不接收WINDOW_UPDATE的情况下发送
    • outboundQueueSize <number> 当前Http2Session的出站队列帧内的帧数
    • deflateDynamicTableSize <number> 出站标头压缩状态表的当前大小(以字节为单位)
    • inflateDynamicTableSize <number> 入站标头压缩状态表的当前大小(以字节为单位)。


1.2.20 http2session.settings(settings)

更新当前本地的Http2Session设置,并发送新的SETTINGS帧到所连接的 HTTP/2 对等端

一旦被调用,http2session.pendingSettingsAck将会设置为true,直到远程方确认新设置。

在收到SETTINGS帧确认并发出'localSettings'事件之前,新设置才会生效。确认仍处于等待状态时,可以发送多个SETTINGS帧。


1.2.21 http2session.type 属性

  • <number>

如果Http2Session实例是一个服务器,则http2session.type等于http2.constants.NGHTTP2_SESSION_SERVER;如果是客户端,则是http2.constants.NGHTTP2_SESSION_CLIENT


1.2.22 http2session.unref()

在当前Http2Session实例底层的net.Socket上调用unref()


1.3 Class: ServerHttp2Session

1.3.1 serverhttp2session.altsvc(alt, originOrStream)

  • alt <string> 由RFC 7838定义的备用服务配置的描述
  • originOrStream <number>>| <string> | <URL> | <Object> 指定源的URL字符串(或具有origin属性的Object)或http2stream.id属性指定的活动Http2Stream的数字标识符。

ALTSVC帧(由RFC 7838定义)提交给所连接的客户端。

const http2 = require('http2');

const server = http2.createServer();
server.on('session', (session) => {
  // Set altsvc for origin https://example.org:80
  session.altsvc('h2=":8000"', 'https://example.org:80');
});

server.on('stream', (stream) => {
  // Set altsvc for a specific stream
  stream.session.altsvc('h2=":8000"', stream.id);
});

发送具有指定流ID的ALTSVC帧指示备用服务并与原始Http2Stream的相关联。

alt与原始字符串必须公包含ASCII字节,并严格解析为ASCII字节序列。 可以传递特殊值'clear'以清除指定域之前设置的任何替代服务。

originOrStream参数传递字符串时,它将被解析为URL并被“源”接收。例如,HTTP URL"https://example.org/foo/bar"的“源”是ASCII字符串"https://example.org"。如果指定字符串无法解析为URL或无法被有效源接收,则会引发错误。

URL对象或有origin属性的任何对象,都可以做为originOrStream传送,这种情况下,将使用origin属性的值。origin属性的值必须是正确的序列化ASCII源。


1.3.2 指定替代服务

alt参数格式被RFC 7838严格定义为ASCII字符串,其中包含逗号分隔与特定主机和端口关联的“替代”("alternative")协议列表。

例如,值'h2="example.org:81"'表示 HTTP/2 协议在 TCP/IP 端口81上的主机'example.org'上可用。主机和端口必须包含在"内。可指定多种替代方案,如:'h2="example.org:81", h2=":82"'

协议标识符(示例中的'h2')可以是任何有效的ALPN协议ID


1.4 Class: ClientHttp2Session

1.4.1 Event: 'altsvc'

事件回调函数参数:

  • alt <string>
  • origin <string>
  • streamId <number>

'altsvc'事件会在客户端收到ALTSVC帧时被发出。事件被发送时会同时包含ALTSVC的值、origin、及流 ID。如果ALTSVC帧中没有origin,则origin为空字符串。

const http2 = require('http2');
const client = http2.connect('https://example.org');

client.on('altsvc', (alt, origin, streamId) => {
  console.log(alt);
  console.log(origin);
  console.log(streamId);
});


1.4.2 Event: 'altsvc'

事件回调函数参数:

  • origins <string[]>

origins事件会在客户端收到ORIGIN帧时被发送。事件发送时会收到origin字符串数组,http2session.originSet会更新为新收到的origins

const http2 = require('http2');
const client = http2.connect('https://example.org');

client.on('origin', (origins) => {
  for (let n = 0; n < origins.length; n++)
    console.log(origins[n]);
});

'origin'事件仅会在使用安全的 TLS 连接时被发送


1.4.3 clienthttp2session.request(headers[, options])

  • headers <HTTP/2 Headers Object>头描述对象
  • headers <object>
    • endStream <boolean>true,如果Http2Stream可写端最初应该关闭。如,发送GET请求而不应该期望有效负载体时。
    • exclusive <boolean>当为trueparent标识一个父流时,创建的流将成为父项的唯一直接依赖项,所有其他现有依赖项将依赖于新创建的流。默认false
    • parent <number>指定新创建的流所依赖的流的数字标识符。
    • weight <number>指定流相对于具有相同parent的其他流的相对依赖性。其取值范围为1256(包含)
    • waitForTrailers <boolean>头描述对象
  • Returns <ClientHttp2Stream>

仅对于 HTTP/2 客户端的Http2Session实例,http2session.request()创建并返回一个Http2Stream实例,该实例可用于向连接的服务器发送 HTTP/2 请求。

该方法仅在http2session.type等于http2.constants.NGHTTP2_SESSION_CLIENT时可用

const http2 = require('http2');
const clientSession = http2.connect('https://localhost:1234');
const {
  HTTP2_HEADER_PATH,
  HTTP2_HEADER_STATUS
} = http2.constants;

const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' });
req.on('response', (headers) => {
  console.log(headers[HTTP2_HEADER_STATUS]);
  req.on('data', (chunk) => { /* .. */ });
  req.on('end', () => { /* .. */ });
});

options.waitForTrailers被设置时,在负载队列发送完最后一块有效负载体后立即发出'wantTrailers'事件。然后可以调用http2stream.sendTrailers()方法将尾随头发送给对方。

options.waitForTrailers被设置,Http2Stream会在最后的DATA帧被发送后关闭。用户可以调用http2stream.sendTrailers()http2stream.close()关闭Http2Stream

:method:path伪标头为设置时,默认为:

  • :method='GET'
  • :path='/'


1.5 Class: Http2Stream

  • Extends: <stream.Duplex>

Http2Stream类的每个实例都表示Http2Session实例上的双向 HTTP/2 通信流。任何单个Http2Session在其生命周期内最多可包含 231-1 Http2Session实例。

用户代码不会直接构造Http2Stream实例,而是通过Http2Session实例创建、管理并提供给用户代码。在服务器端,创建Http2Session实例以响应传入的HTTP请求(并通过'stream'事件传递给用户代码),或响应对http2stream.pushStream()方法的调用;在客户端,当调用http2session.request()方法或响应传入的'push'事件,将创建关返回Http2Session实例。

Http2Stream类是ServerHttp2StreamClientHttp2Stream类的基础,每个类分别由服务器端或客户端使用。

所有Http2Session实例都是“双工”流。在双工的Writable端用于向连接的对等端发送数据,而Readable端用于接收由连接的对等端发送的数据。


1.5.1 Http2Stream 的生命周期

创建

在服务器端ServerHttp2Stream实例会在以下两种情况下创建:

  • 收到有以前未使用的流Id的新的 HTTP/2 HEADERS帧时。
  • http2stream.pushStream()方法被调用时

在客户端ClientHttp2Stream实例会在http2session.request()方法被调用时创建

在客户端上,如果父Http2Session实例尚未完全建立,则http2session.request()返回的Http2Stream实例可能无法立即使用。这时,调用Http2Stream的操作将被缓冲,直到发出'ready'事件。一般来说,用户代码很少需要直接处理'ready'事件。可以通过检查http2stream.id的值来确定Http2Stream是否是就绪状态,如果值是undefined,则流是未就绪状态。


销毁

Http2Stream实例会在以下情况下销毁:

  • 所连接的对等端收到流的RST_STREAM帧时
  • http2stream.close()方法被调用时
  • http2stream.destroy()http2session.destroy()方法被调用时

Http2Stream销毁时,会尝试发送一个RST_STREAM帧到对等端。

Http2Stream销毁时,'close'事件会被发出。由于Http2Stream是一个stream.Duplex实例,当流还在流动时同样会发出'end'事件。调用http2stream.destroy()方法并在第一个参数中传入Error时,同样会发出'error'事件。

Http2Stream被销毁后,http2stream.destroyed属性会设置为truehttp2stream.rstCode会被设置为具体的错误码。Http2Stream实例也不再可用。


1.5.2 Http2Stream中的事件

Event: 'aborted'

每当Http2Stream实例在通信中间异常中止时,就会发出'aborted'事件。

只有在Http2Stream可写端未结束时才会发出'aborted'事件。


Event: 'close'

Http2Stream被销毁时会发出'close'事件。 一旦发出此事件,Http2Stream实例就不再可用。

可以通过http2stream.rstCode属性检查关闭流时所使用的 HTTP/2 错误码。如果代码是NGHTTP2_NO_ERROR(0)以外的任何值,则还会发出'error'事件。


Event: 'error'
  • error <Error>

在处理Http2Stream期间发生错误时会发出error事件。


Event: 'frameError'

尝试发送帧时发生错误会发出'frameError'事件。调用回调处理函数时,将收到标识帧类型的整数参数和标识错误代码的整数参数。发出'frameError'事件后,Http2Stream实例将立即销毁。


Event: 'timeout'

在使用http2stream.setTimeout()设置的毫秒数内未收到此Http2Stream的任何活动时,将发出'timeout'事件。


Event: 'trailers'

当收到与尾随头字段相关联的头数据块时,将发出'trailers'事件。回调函数中会包含HTTP/2 Headers Object头描述对象及与头相关联的标志。

需要注意,如果在接收到尾随头数据(trailing header)之前调用http2stream.end(),或收到传入数据未读取,则可能不会发出此事件。

stream.on('trailers', (headers, flags) => {
  console.log(headers);
});


Event: 'wantTrailers'

Http2Stream将最终DATA帧排队到等待在帧上发送并且Http2Stream准备好发送尾随头时,会发出'wantTrailers'事件。启动请求或响应时,必须设置waitForTrailers选项才能发出此事件。


1.5.3 http2stream.aborted 属性

  • <boolean>

如果Http2Stream实例异常中止,则设置为true。设置后,将发出'aborted'事件。


1.5.4 http2stream.close(code[, callback])

  • code <number> 无符号32位整型的错误码。默认为http2.constants.NGHTTP2_NO_ERROR (0x00)
  • callback <function> 可选的用于监听'close'事件的回调函数

通过向连接的 HTTP/2 对等端发送RST_STREAM帧来关闭Http2Stream实例。


1.5.5 http2stream.closed 属性

  • <boolean>

Http2Stream关闭后,则设置为true


1.5.6 http2stream.destroyed 属性

  • <boolean>

Http2Stream实例已被销毁且不再可用,则设置为true


1.5.7 http2stream.endAfterHeaders 属性

  • <boolean>

如果在收到的请求或响应的HEADERS帧中设置了END_STREAM标志,则设置为true,这时不应接收其他数据,并且Http2Stream的可读侧将关闭


1.5.8 http2stream.pending 属性

  • <boolean>

如果还没有为Http2Stream实例分配数字流标识符,则设置为true


1.5.9 http2stream.priority(options)

  • options <Object>
    • exclusive - <boolean> 当为trueparent标识父Stream时,此流将为父对象的唯一直接依赖关系。默认为false
    • parent - <number> 指定此流所依赖的流的数字标识符
    • weight - <number> 指定流相对于具有相同父级的其他流的相对依赖性。取值范围为1256(含)之间的数字
    • silent - <boolean> 如果为true,则在本地更改优先级,而不向连接的对等端发送PRIORITY帧。

更新此Http2Stream实例的优先级。


1.5.10 http2stream.rstCode 属性

  • <number>

设置为在从连接的对等方接收RST_STREAM帧时,调用http2stream.close()http2stream.destroy()销毁Http2Stream时所报告的RST_STREAM错误代码。如果Http2Stream尚未关闭时,将不确定。


1.5.11 http2stream.sentHeaders 属性

包含为此Http2Stream实例发送的出站标头的对象。


1.5.12 http2stream.sentInfoHeaders 属性

包含为此Http2Stream实例发送的出站信息标头的对象数组。


1.5.13 http2stream.sentTrailers 属性

包含为此Http2Stream发送的出站trailers的对象。


1.5.14 http2stream.session 属性

对拥有此Http2StreamHttp2Session实例的引用。Http2Stream实例被销毁后,该值将是undefined


1.5.15 http2stream.setTimeout(msecs, callback)

  • msecs <number>
  • callback <Function>
const http2 = require('http2');
const client = http2.connect('http://example.org:8000');
const { NGHTTP2_CANCEL } = http2.constants;
const req = client.request({ ':path': '/' });

// Cancel the stream if there's no activity after 5 seconds
req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));


1.5.16 http2stream.state 属性

当前Http2Stream的各种状态信息

  • <Object>
    • localWindowSize <number> 连接的对等方可以为此Http2Stream发送的字节数,而不接收WINDOW_UPDATE
    • state <number> 一个标志,指示由nghttp2确定的Http2Stream的低级当前状态
    • localClose <number> 当前Http2Stream在本地关闭时,则为true
    • remoteClose <number> 当前Http2Stream在远程关闭时,则为true
    • sumDependencyWeight <number> 依赖于使用PRIORITY帧指定的此Http2Stream的所有Http2Stream实例的总权重和。
    • weight <number> 当前Http2Stream的优先级权重


1.5.17 http2stream.sendTrailers(headers)

将尾随HEADERS帧发送到连接的 HTTP/2 对等方。此方法将导致Http2Stream立即关闭,且只能在发出'wantTrailers'事件后调用。发送请求或发送响应时,必须设置options.waitForTrailers选项,以便在最终DATA帧之后保持Http2Stream打开,以便可以发送尾随预告。

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  stream.respond(undefined, { waitForTrailers: true });
  stream.on('wantTrailers', () => {
    stream.sendTrailers({ xyz: 'abc' });
  });
  stream.end('Hello World');
});

注意,在 HTTP/1 规范禁止尾随预告包含 HTTP/2 伪标头字段(例如':method'':path'等)。


1.6 Class: ClientHttp2Stream

ClientHttp2Stream类是对Http2Stream的扩展,专用于 HTTP/2 客户端。会在客户端上的Http2Stream实例提供仅与客户端相关的事件,例如'response''push'

1.6.1 Event: 'continue'

当服务器发送 100 Continue 状态时发出,通常是因为请求中包含Expect:100-continue。这是客户端应发送请求体的指令。


1.6.2 Event: 'headers'

当收到流的附加头块时,如当接收到1xx信息头块时,将发出'headers'事件。临听回调函数会传递 HTTP/2 HTTP/2 Headers Object和与标头相关的标志。

stream.on('headers', (headers, flags) => {
  console.log(headers);
});


1.6.3 Event: 'push'

收到服务器推送流的响应头时,会发出'push'事件。临听回调函数会传递 HTTP/2 HTTP/2 Headers Object和与标头相关的标志。


1.6.4 Event: 'response'

当从连接的 HTTP/2 服务器收到此流的响应HEADERS帧时,将发出'response'事件。临听回调函数包含两个参数:HTTP/2 Headers Object和与标头相关的标志。

const http2 = require('http2');
const client = http2.connect('https://localhost');
const req = client.request({ ':path': '/' });
req.on('response', (headers, flags) => {
  console.log(headers[':status']);
});


1.7 Class: ServerHttp2Stream

ServerHttp2Stream类同样是对Http2Stream的扩展,专用于 HTTP/2 服务器端。会在服务器上提供相关方法,如http2stream.pushStream()http2stream.respond()等。


1.7.1 http2stream.additionalHeaders(headers)

向连接的 HTTP/2 对等方发送附加HEADERS信息帧。


1.7.2 http2stream.headersSent 属性

  • <boolean>

头信息发送后为ture,其它情况为false(只读)


1.7.3 http2stream.pushAllowed 属性

  • <boolean>

只读属性映射到远程客户端最新SETTINGS帧的SETTINGS_ENABLE_PUSH标志。

如果远程对等方接受推送流,则为true,否则为false。同一个Http2Session中的每个Http2Stream的设置都是相同的。


1.7.4 http2stream.pushStream(headers[, options], callback)

  • headers <HTTP/2 Headers Object>
  • options <object>
    • exclusive <boolean>当为trueparent标识一个父流时,创建的流将成为父项的唯一直接依赖项,所有其他现有依赖项将依赖于新创建的流。默认false
    • parent <number>指定新创建的流所依赖的流的数字标识符。
  • callback <function>推送流启动调用的回调函数,其有以下三个参数:
    • err <Error>
    • pushStream <number>返回的pushStream对象。
    • headers <HTTP/2 Headers Object> 启动pushStream的Headers对象。

启动推送流。回调函数会在Http2Stream实例创建时调用,如果没有错误其实例会传递到第二个参数,有错则将Error作为第一个参数。

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  stream.respond({ ':status': 200 });
  stream.pushStream({ ':path': '/' }, (err, pushStream, headers) => {
    if (err) throw err;
    pushStream.respond({ ':status': 200 });
    pushStream.end('some pushed data');
  });
  stream.end('some data');
});

不允许在HEADERS帧中设置流权重。而是应该将weight值传递给http2stream.priority,并将silent选项设置为true,以在并发流之间启用服务器端带宽平衡。

不允许在所推送的流中调用http2stream.pushStream(),调用将引发错误。


1.7.5 http2stream.respond([headers[, options]])

  • headers <HTTP/2 Headers Object>
  • options <object>
    • endStream <boolean> 设置为true表示响应中不包含有效负载数据。
    • waitForTrailers <boolean> 如果为true,则Http2Stream将在发送最终DATA帧后发出'wantTrailers'事件。
const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  stream.respond({ ':status': 200 });
  stream.end('some data');
});

设置options.waitForTrailers选项后,在队列中的最后一块有效负载数据发送后,会立即发出'wantTrailers'事件。然后可以通过http2stream.sendTrailers()方法将尾随头字段发送给对等方。

设置options.waitForTrailersHttp2Stream 在传输最终DATA帧时不会自动关闭。用户代码必须调用http2stream.sendTrailers()http2stream.close() 才能关闭Http2Stream

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  stream.respond({ ':status': 200 }, { waitForTrailers: true });
  stream.on('wantTrailers', () => {
    stream.sendTrailers({ ABC: 'some value to send' });
  });
  stream.end('some data');
});


1.7.6 http2stream.respondWithFD(fd[, headers[, options]])

  • fd <number> 可读的文件描述符
  • headers <HTTP/2 Headers Object>
  • options <object>
    • statCheck <Funtion>
    • waitForTrailers <boolean> 当为true时,Http2Stream会在发送完最终的DATA帧后发出'wantTrailers'事件。
    • offset <number> 开始读取的偏移位置。
    • length <number> 从fd发送的数据量。

启动从指定文件描述符读取数据的响应。不对指定的文件描述符进行验证。如果在尝试使用文件描述符读取数据时发生错误,则将使用标准的INTERNAL_ERROR代码使用RST_STREAM帧关闭Http2Stream

使用时,Http2Stream对象的Duplex接口将自动关闭。

const http2 = require('http2');
const fs = require('fs');

const server = http2.createServer();
server.on('stream', (stream) => {
  const fd = fs.openSync('/some/file', 'r');

  const stat = fs.fstatSync(fd);
  const headers = {
    'content-length': stat.size,
    'last-modified': stat.mtime.toUTCString(),
    'content-type': 'text/plain'
  };
  stream.respondWithFD(fd, headers);
  stream.on('close', () => fs.closeSync(fd));
});

可以指定可选的options.statCheck函数,以便用户代码可以基于指定fd的fs.Stat详细信息来设置其他内容头。 如果提供了statCheck函数,http2stream.respondWithFD()方法将执行fs.fstat()调用以收集所提供的文件描述符的详细信息。

offsetlength选项可用于限制对指定范围子集进行响应。

文件描述符不会随流的关闭而关闭,所以需要在不使用后手工将其关闭。注意,不支持同时为多个流使用相同的文件描述符,这可能会导致数据丢失。在流完成后可以重新使用文件描述符。

const http2 = require('http2');
const fs = require('fs');

const server = http2.createServer();
server.on('stream', (stream) => {
  const fd = fs.openSync('/some/file', 'r');

  const stat = fs.fstatSync(fd);
  const headers = {
    'content-length': stat.size,
    'last-modified': stat.mtime.toUTCString(),
    'content-type': 'text/plain'
  };
  stream.respondWithFD(fd, headers, { waitForTrailers: true });
  stream.on('wantTrailers', () => {
    stream.sendTrailers({ ABC: 'some value to send' });
  });

  stream.on('close', () => fs.closeSync(fd));
});


1.7.7 http2stream.respondWithFD(fd[, headers[, options]])

  • path <string>|<Buffer>|<URL>
  • headers <HTTP/2 Headers Object>
  • options <object>
    • statCheck <Funtion>
    • onError <Funtion> 在发送之前发生错误时所调用的回调函数。
    • waitForTrailers <boolean> 当为true时,Http2Stream会在发送完最终的DATA帧后发出'wantTrailers'事件。
    • offset <number> 开始读取的偏移位置。
    • length <number> 从fd发送的数据量。

发送常规文件作为响应。path必须指定常规文件,否则将在Http2Stream对象上发出'error'事件。

使用时,Http2Stream对象的Duplex接口将自动关闭。

可以指定可选的options.statCheck函数,以便用户代码可以基于给定文件的fs.Stat详细信息设置其他内容标头。

如果在尝试读取文件数据时发生错误,将使用标准INTERNAL_ERROR代码并使用RST_STREAM帧关闭又Http2Stream。如果定义了onError回调,将会被调用。否则流将被销毁。

可以如下所示使用文件路径:

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  function statCheck(stat, headers) {
    headers['last-modified'] = stat.mtime.toUTCString();
  }

  function onError(err) {
    if (err.code === 'ENOENT') {
      stream.respond({ ':status': 404 });
    } else {
      stream.respond({ ':status': 500 });
    }
    stream.end();
  }

  stream.respondWithFile('/some/file',
                         { 'content-type': 'text/plain' },
                         { statCheck, onError });
});

options.statCheck函数也可用于通过返回false来取消发送操作。 例如,条件请求可以检查统计结果以确定文件是否已被修改,以返回适用的304响应:

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  function statCheck(stat, headers) {
    // Check the stat here...
    stream.respond({ ':status': 304 });
    return false; // Cancel the send operation
  }
  stream.respondWithFile('/some/file',
                         { 'content-type': 'text/plain' },
                         { statCheck });
});

在上例中,content-length 头会自动设置。

offsetlength选项可用于限制对指定范围子集进行响应。

options.onError函数可用于处理在启动文件传递之前可能发生的所有错误。默认行为是销毁流。

设置options.waitForTrailers选项后,将在发送队列中的最后一块有效负载数据后立即发出'wantTrailers'事件。然后可以使用http2stream.sendTrilers()方法向对等方发送尾随标头字段。

设置options.waitForTrailers时,Http2Stream在传输最终DATA帧时不会自动关闭。用户代码必须调用http2stream.sendTrailers()或http2stream.close()来关闭。

const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream) => {
  stream.respondWithFile('/some/file',
                         { 'content-type': 'text/plain' },
                         { waitForTrailers: true });
  stream.on('wantTrailers', () => {
    stream.sendTrailers({ ABC: 'some value to send' });
  });
});


1.8 Class: Http2Server

  • Extends<net.Server>

http2模块不直接导出Http2Server类,其实例通过http2.createServer()函数创建的。


1.8.1 Http2Server中的事件

Event: 'checkContinue'

如果已注册'request'监听器或http2.createServer()提供了回调函数,'checkContinue'事件会在每次收到HTTP Expect: 100-continue请求时发出。如果未添加事件监听器,服务器会自动响应100 Continue状态。

处理此事需要调用response.writeContinue(),如果客户端应继续发送请求体,或者如果客户端不应继续发送请求体,则生成适当的HTTP响应(如:400 Bad Request)。

需要注意,发出和处理此事件时,不会发出'request'事件。


Event: 'request'

每次有请求时都会发出本事件。需要注意,每个会话都可能会有多个请求。请参阅兼容性API


Event: 'session'

Http2Server每次创建一个新的Http2Session时,都会发出'session'事件。


Event: 'sessionError'

当与Http2Server关联的Http2Session对象发出'error'事件时,会发出'sessionError'事件。


Event: 'stream'

当与Http2Server关联的Http2Session对象发出'stream'事件时,会发出'stream'事件。

const http2 = require('http2');
const {
  HTTP2_HEADER_METHOD,
  HTTP2_HEADER_PATH,
  HTTP2_HEADER_STATUS,
  HTTP2_HEADER_CONTENT_TYPE
} = http2.constants;

const server = http2.createServer();
server.on('stream', (stream, headers, flags) => {
  const method = headers[HTTP2_HEADER_METHOD];
  const path = headers[HTTP2_HEADER_PATH];
  // ...
  stream.respond({
    [HTTP2_HEADER_STATUS]: 200,
    [HTTP2_HEADER_CONTENT_TYPE]: 'text/plain'
  });
  stream.write('hello ');
  stream.end('world');
});


Event: 'timeout'

当使用http2server.setTimeout()设置指定的毫秒数时,如果服务器上没有活动会发出timeout''事件。默认值:2分钟。


1.8.2 server.close([callback])

  • callback <Function>

停止服务器接收新的链接。这与限制新请求不同,因为 HTTP/2 连接是持久连接。要实现类似的正常关闭行为,请在活动会话上使用http2session.close()


1.8.3 server.setTimeout([msecs][, callback])

  • msecs <number> 超时时间,默认:120000(2分)
  • callback <Function>
  • Returns <Http2Server>

设置 http2 服务器请求的超时值,并设置在msecs毫秒后Http2Server上没有活动时调用的回调函数。

如果没有指定回调函数,将抛出新的ERR_INVALID_CALLBACK错误。


1.9 Class: Http2SecureServer

  • Extends<tls.Server>

类似于Http2ServerHttp2SecureServer的实例使用http2.createSecureServer()函数创建的。http2模块同样没有直接导出Http2SecureServer类。


1.9.1 Http2SecureServer中的事件

Event: 'checkContinue'

如果注册了'request'监听器或者为http2.createSecureServer()提供了回调函数,则每次收到HTTP Expect:100-continue状态的请求时都会发出'checkContinue'事件。如果监听此事件,则服务器将自动响应100 Continue状态。

处理此事需要调用response.writeContinue(),如果客户端应继续发送请求体,或者如果客户端不应继续发送请求体,则生成适当的HTTP响应(如:400 Bad Request)。

需要注意,发出和处理此事件时,不会发出'request'事件。


Event: 'request'

每次有请求时都会发出本事件。需要注意,每个会话都可能会有多个请求。请参阅兼容性API


Event: 'session'

Http2SecureServer每次创建一个新的Http2Session时,都会发出'session'事件。


Event: 'sessionError'

当与Http2SecureServer关联的Http2Session对象发出'error'事件时,会发出'sessionError'事件。


Event: 'stream'

当与Http2SecureServer关联的Http2Session对象发出'stream'事件时,会发出'stream'事件。

const http2 = require('http2');
const {
  HTTP2_HEADER_METHOD,
  HTTP2_HEADER_PATH,
  HTTP2_HEADER_STATUS,
  HTTP2_HEADER_CONTENT_TYPE
} = http2.constants;

const options = getOptionsSomehow();

const server = http2.createSecureServer(options);
server.on('stream', (stream, headers, flags) => {
  const method = headers[HTTP2_HEADER_METHOD];
  const path = headers[HTTP2_HEADER_PATH];
  // ...
  stream.respond({
    [HTTP2_HEADER_STATUS]: 200,
    [HTTP2_HEADER_CONTENT_TYPE]: 'text/plain'
  });
  stream.write('hello ');
  stream.end('world');
});


Event: 'timeout'

当使用http2secureserver.setTimeout()设置指定的毫秒数时,如果服务器上没有活动会发出timeout''事件。默认值:2分钟。


Event: 'unknownProtocol'

当连接客户端无法协商允许的协议(即 HTTP/2 或 HTTP/1.1)时,会发出'unknownProtocol'事件。事件处理程序接收用于处理的套接字。如果没有为此事件注册监听器,则终止连接。


1.9.2 server.close([callback])

  • callback <Function>

停止服务器接收新的链接。这与限制新请求不同,因为 HTTP/2 连接是持久连接。要实现类似的正常关闭行为,请在活动会话上使用http2session.close()


1.9.3 server.setTimeout([msecs][, callback])

  • msecs <number> 超时时间,默认:120000(2分)
  • callback <Function>
  • Returns <Http2SecureServer>

设置 http2 服务器请求的超时值,并设置在msecs毫秒后Http2Server上没有活动时调用的回调函数。

如果没有指定回调函数,将抛出新的ERR_INVALID_CALLBACK错误。


1.10 http2.createServer(options[, onRequestHandler])

  • options <Object>
    • maxDeflateDynamicTableSize <number>设置压缩头字段的最大动态表大小。默认:4Kib.
    • maxSessionMemory <number>

      设置允许Http2Session使用的最大内存。

      其表示单位为兆字(MB)。允许的最小值为1,这是基于信用的限制,现有的Http2Stream可能会导致超出这一限制,当超出此限制时,将拒绝新的Http2Stream实例。当前Http2Stream会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PINGSETTINGS帧都计入当前限制。

    • maxHeaderListPairs <number> 设置标头条目的最大数量。最小值是4。默认:128
    • maxOutstandingPings <number> 设置未完成的、未确认的 ping 数量。默认:10
    • maxSendHeaderBlockLength <number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'事件并关闭和销毁流。
    • paddingStrategy <number> 标识用于确定用于HEADERSDATA帧的填充量的策略。默认: http2.constants.PADDING_STRATEGY_NONE。其可能是以值之一:
      • http2.constants.PADDING_STRATEGY_NONE - 不使用填充。
      • http2.constants.PADDING_STRATEGY_MAX - 由内部实现确定的最大填充量
      • http2.constants.PADDING_STRATEGY_CALLBACK - 由用户调用options.selectPadding()回调来确定填充量。
      • http2.constants.PADDING_STRATEGY_ALIGNED - 尝试应用足够的填充以确保包括9字节标头在内的总帧长度是8的倍数。但是,每个帧都有一个允许的最大填充字节数。则由当前流量控制状态和设置决定。 如果此最大值小于确保对齐所需的计算量,则将使用最大值,并且总帧长度不一定以8个字节对齐。
    • peerMaxConcurrentStreams <number> 设置远程对等方的最大并发流数,就像收到SETTINGS帧一样。 如果远程对等方为maxConcurrentStreams,自己设置的值将被覆盖。默认:100
    • selectPadding <Function> 当options.paddingStrategy等于http2.constants.PADDING_STRATEGY_CALLBACK时,提供用于确定填充的回调函数。
    • settings <HTTP/2 Settings Object> 连接时发送到远程对等方的初始设置。
    • Http1IncomingMessage <http.IncomingMessage> 指定用于 HTTP/1 回退的IncomingMessage类。 用于扩展原始的http.IncomingMessage。默认:http.IncomingMessage
    • Http1ServerResponse <http.ServerResponse> 指定用于 HTTP/1 回退的ServerResponse。用于扩展原始的 http.ServerResponse。默认: http.ServerResponse
    • Http2ServerRequest <http2.Http2ServerRequest> 指定要使用的Http2ServerRequest类。用于扩展原始的Http2ServerRequest。默认:Http2ServerRequest
    • Http2ServerResponse< http2.Http2ServerResponse> 指定要使用的 Http2ServerResponse类。用于扩展原始Http2ServerResponse。默认:Http2ServerResponse
  • onRequestHandler <Function> 见:兼容API
  • 返回:Http2Server

创建一个用于创建和管理Http2Session实例的net.Server实例。

目前已知的浏览器还没有支持未加密的 HTTP/2,所以在与浏览器客户端通信时需要使用http2.createSecureServer()

const http2 = require('http2');

// 创建未加密的 HTTP/2 服务器
// 目前已知的浏览器还没有支持 未加密的 HTTP/2
// 所以,在与浏览器客户端通信时需要使用  `http2.createSecureServer()`
const server = http2.createServer();

server.on('stream', (stream, headers) => {
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.end('<h1>Hello World</h1>');
});

server.listen(80);


1.11 http2.createSecureServer(options[, onRequestHandler])

  • options <Object>
    • allowHTTP1 <boolean> 当设置为true时,不支持 HTTP/2 的传入客户端连接将降级为 HTTP/1.x。请参阅'unknownProtocol'事件及ALPN 协商。默认:false
    • maxDeflateDynamicTableSize <number>设置压缩头字段的最大动态表大小。默认:4Kib.
    • maxSessionMemory <number>

      设置允许Http2Session使用的最大内存。

      其表示单位为兆字(MB)。允许的最小值为1,这是基于信用的限制,现有的Http2Stream可能会导致超出这一限制,当超出此限制时,将拒绝新的Http2Stream实例。当前Http2Stream会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PINGSETTINGS帧都计入当前限制。默认:10

    • maxHeaderListPairs <number> 设置标头条目的最大数量。最小值是4。默认:128
    • maxOutstandingPings <number> 设置未完成的、未确认的 ping 数量。默认:10
    • maxSendHeaderBlockLength <number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'事件并关闭和销毁流。
    • paddingStrategy <number> 标识用于确定用于HEADERSDATA帧的填充量的策略。默认: http2.constants.PADDING_STRATEGY_NONE。其可能是以值之一:
      • http2.constants.PADDING_STRATEGY_NONE - 不使用填充。
      • http2.constants.PADDING_STRATEGY_MAX - 由内部实现确定的最大填充量
      • http2.constants.PADDING_STRATEGY_CALLBACK - 由用户调用options.selectPadding()回调来确定填充量。
      • http2.constants.PADDING_STRATEGY_ALIGNED - 尝试应用足够的填充以确保包括9字节标头在内的总帧长度是8的倍数。但是,每个帧都有一个允许的最大填充字节数。则由当前流量控制状态和设置决定。 如果此最大值小于确保对齐所需的计算量,则将使用最大值,并且总帧长度不一定以8个字节对齐。
    • peerMaxConcurrentStreams <number> 设置远程对等方的最大并发流数,就像收到SETTINGS帧一样。 如果远程对等方为maxConcurrentStreams,自己设置的值将被覆盖。默认:100
    • selectPadding <Function> 当options.paddingStrategy等于http2.constants.PADDING_STRATEGY_CALLBACK时,提供用于确定填充的回调函数。
    • settings <HTTP/2 Settings Object> 连接时发送到远程对等方的初始设置。
    • ... 任何tls.createServer()选项都可以提供。对于服务器来说,通常需要标识选项(pfxkey/cert)。
    • origins <string[]> 在创建新服务器Http2Session之后,通过ORIGIN帧立即发送的原始字符串数组。
  • onRequestHandler <Function> 见:兼容API
  • 返回:Http2Server

返回创建和管理Http2Session实例的tls.Server实例。

const http2 = require('http2');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem')
};

// Create a secure HTTP/2 server
const server = http2.createSecureServer(options);

server.on('stream', (stream, headers) => {
  stream.respond({
    'content-type': 'text/html',
    ':status': 200
  });
  stream.end('<h1>Hello World</h1>');
});

server.listen(80);


1.12 http2.connect(authority[, options][, listener])

  • authority <string>|<URL>
  • options <Object>
    • maxDeflateDynamicTableSize <number>设置压缩头字段的最大动态表大小。默认:4Kib.
    • maxSessionMemory <number>

      设置允许Http2Session使用的最大内存。

      其表示单位为兆字(MB)。允许的最小值为1,这是基于信用的限制,现有的Http2Stream可能会导致超出这一限制,当超出此限制时,将拒绝新的Http2Stream实例。当前Http2Stream会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PINGSETTINGS帧都计入当前限制。默认:10

    • maxHeaderListPairs <number> 设置标头条目的最大数量。最小值是4。默认:128
    • maxOutstandingPings <number> 设置未完成的、未确认的 ping 数量。默认:10
    • maxReservedRemoteStreams <number> 设置客户端在指定时间可接受的最大保留推送流数。一旦当前保留的推送流的数量超过此限制,服务器发送的新推送流将被自动拒绝。
    • maxSendHeaderBlockLength <number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'事件并关闭和销毁流。
    • paddingStrategy <number> 标识用于确定用于HEADERSDATA帧的填充量的策略。默认: http2.constants.PADDING_STRATEGY_NONE。其可能是以值之一:
      • http2.constants.PADDING_STRATEGY_NONE - 不使用填充。
      • http2.constants.PADDING_STRATEGY_MAX - 由内部实现确定的最大填充量
      • http2.constants.PADDING_STRATEGY_CALLBACK - 由用户调用options.selectPadding()回调来确定填充量。
      • http2.constants.PADDING_STRATEGY_ALIGNED - 尝试应用足够的填充以确保包括9字节标头在内的总帧长度是8的倍数。但是,每个帧都有一个允许的最大填充字节数。则由当前流量控制状态和设置决定。 如果此最大值小于确保对齐所需的计算量,则将使用最大值,并且总帧长度不一定以8个字节对齐。
    • peerMaxConcurrentStreams <number> 设置远程对等方的最大并发流数,就像收到SETTINGS帧一样。 如果远程对等方为maxConcurrentStreams,自己设置的值将被覆盖。默认:100
    • selectPadding <Function> 当options.paddingStrategy等于http2.constants.PADDING_STRATEGY_CALLBACK时,提供用于确定填充的回调函数。
    • settings <HTTP/2 Settings Object> 连接时发送到远程对等方的初始设置。
    • createConnection <Function> 一个可选的回调函数,它接收传递给connectoptions对象的URL实例,并返回任何将用作此会话连接的Duplex流。
    • ... 任何net.connect()tls.connect()选项中的参数都可以提供。
  • listener <Function>
  • 返回:<ClientHttp2Session>
const http2 = require('http2');
const client = http2.connect('https://localhost:1234');

/* Use the client */

client.close();


1.13 http2.constants 属性

RST_STREAM和GOAWAY的错误码:

代码名 常量
0x00No Errorhttp2.constants.NGHTTP2_NO_ERROR
0x01Protocol Errorhttp2.constants.NGHTTP2_PROTOCOL_ERROR
0x02Internal Errorhttp2.constants.NGHTTP2_INTERNAL_ERROR
0x03Flow Control Errorhttp2.constants.NGHTTP2_FLOW_CONTROL_ERROR
0x04Settings Timeouthttp2.constants.NGHTTP2_SETTINGS_TIMEOUT
0x05Stream Closedhttp2.constants.NGHTTP2_STREAM_CLOSED
0x06Frame Size Errorhttp2.constants.NGHTTP2_FRAME_SIZE_ERROR
0x07Refused Streamhttp2.constants.NGHTTP2_REFUSED_STREAM
0x08Cancelhttp2.constants.NGHTTP2_CANCEL
0x09Compression Errorhttp2.constants.NGHTTP2_COMPRESSION_ERROR
0x0aConnect Errorhttp2.constants.NGHTTP2_CONNECT_ERROR
0x0bEnhance Your Calmhttp2.constants.NGHTTP2_ENHANCE_YOUR_CALM
0x0cInadequate Securityhttp2.constants.NGHTTP2_INADEQUATE_SECURITY
0x0dHTTP/1.1 Requiredhttp2.constants.NGHTTP2_HTTP_1_1_REQUIRED

使用http2server.setTimeout()设置毫秒数时,服务器在指定时间内没有活动时会发出'timeout'事件。


1.14 http2.getDefaultSettings()

返回包含ttp2SessionH实例的默认设置的对象。每次调用此方法时,此方法都会返回一个新对象实例,因此可以安全地修改所返回的实例以供使用。


1.15 http2.getPackedSettings(settings)

返回一个Buffer实例,其中包含 HTTP/2 规范中指定的给定 HTTP/2 设置的序列化表示形式。这适用于HTTP2-Settings标头字段。

const http2 = require('http2');

const packed = http2.getPackedSettings({ enablePush: false });

console.log(packed.toString('base64'));
// Prints: AAIAAAAA


1.16 http2.getUnpackedSettings(buf)

返回HTTP/2 设置对象,其中包含由http2.getPackedSettings()生成的给定Buffer中的反序列化设置。


1.17 Headers 对象

标头在JavaScript对象上表示为自己的属性。其中属性键将序列化为小写,属性值应该是字符串(如果它们不是强制转换为字符串)或字符串数组(为了每个标题字段发送多个值)。

const headers = {
  ':status': '200',
  'content-type': 'text-plain',
  'ABC': ['has', 'more', 'than', 'one', 'value']
};

stream.respond(headers);

传递给回调函数的头对象将会有null属性。这意味着普通的JavaScript对象方法(如Object.prototype.toString()Object.prototype.hasOwnProperty())将不起作用。

对于传入头来说:

  • :status标头转换为number
  • 重复项 :status:method:authority:scheme:path:protocolageauthorizationaccess-control-allow-credentialsaccess-control-max-ageaccess-control-request-methodcontent-encodingcontent-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typedatedntetagexpiresfromif-matchif-modified-sinceif-none-matchif-rangeif-unmodified-sincelast-modified, locationmax-forwards, proxy-authorizationrangereferer,retry-aftertkupgrade-insecure-requestsuser-agentx-content-type-options将舍弃。
  • set-cookie总是数组。重复项将添加到数组中。
  • cookie值将使用';'连接在一起。
  • 所有其它标头,将使用','连接在一起。
const http2 = require('http2');
const server = http2.createServer();
server.on('stream', (stream, headers) => {
  console.log(headers[':path']);
  console.log(headers.ABC);
});


1.18 设置对象

http2.getDefaultSettings()http2.getPackedSettings()http2.createServer()http2.createSecureServer()http2session.settings()http2session.localSettingshttp2session.remoteSettingsAPI作为输入返回或接收定义Http2Session对象的配置设置的对象。这些对象是包含以下内容的普通JavaScript对象 属性。

  • headerTableSize <number> 指定用于标头压缩的最大字节数。允许的最小值为0,最大值为232-1。默认:4,096 octets
  • enablePush <boolean> 如果要在Http2Session实例上允许 HTTP/2 推送流,则设置为true
  • initialWindowSize <number> 指定控制流的发件人初始窗口大小。允许的最小值为0,最大值为232-1。默认:65,535 bytes
  • maxFrameSize <<number> 指定最大帧有效负载的大小。允许的最小值为16,384,最大值为224-1。默认:16,384 bytes
  • maxConcurrentStreams <number> 指定Http2Session上允许的最大并发流数。没有默认值意味着,理论上至少,231-1。流可以在Http2Session中的任何给定时间同时打开。 最小值为0,最大值为231-1。
  • maxHeaderListSize <number>指定将接受的标头列表的最大大小(未压缩的八位字节)。允许的最小值为0,232-1。默认值:code>65535。
  • enableConnectProtocol <boolean> 如果要启用RFC 定义的“扩展连接协议”("Extended Connect Protocol"),则指定true。此设置仅在服务器发送时才有意义。一旦为code>Http2Session启用了enableConnectProtocol设置,就无法禁用它。

将忽略设置对象上的所有其他属性。


1.19 使用`options.selectPadding()`

options.paddingStrategy等于http2.constants.PADDING_STRATEGY_CALLBACK时,HTTP/2 实现将参考options.selectPadding()回调函数(如果提供),以确定每个HEADERSDATA帧使用的特定填充量。

options.selectPadding()函数接收两个数字参数frameLenmaxFrameLen,并且必须返回一个数字N,使得frameLen <= N <= maxFrameLen

const http2 = require('http2');
const server = http2.createServer({
  paddingStrategy: http2.constants.PADDING_STRATEGY_CALLBACK,
  selectPadding(frameLen, maxFrameLen) {
    return maxFrameLen;
  }
});

options.selectPadding()函数为每个HEADERSDATA帧调用一次。这会对性能有明显的影响。


1.20 错误处理

使用http2模块时可能会出现几种类型的错误情况:

  • 传入不正确的参数、选项或设置值时会发生验证错误。这些错误始终由同步throw报告。
  • 在不正确的时间尝试操作时发生状态错误(如,尝试在关闭后在流上发送数据)。这些将使用Http2StreamHttp2Session或 HTTP/2 Server 对象上的同步throw'error'事件进行报告,具体取决于错误发生的位置和时间。
  • HTTP/2 会话意外失败时发生内部错误。这些将通过Http2Session或 HTTP/2 服务器对象上的'error'事件进行报告。
  • 当违反 HTTP/2 各种协议约束时,会发生协议错误。这些将使用Http2StreamHttp2Session或 HTTP/2 Server 对象上的同步throw'error'事件进行报告,具体取决于错误发生的位置和时间。


1.21 标头字段名和值中的无效字符处理

与 HTTP/1 的实现相比,HTTP/2 在HTTP头名称和值中应更严格的对无效字符进行处理。

标题字段名称不区分大小写,并严格地作为小写字符串进行传输。Node.js提供的API允许标题名称被设置为混合大小写字符串(如Content-Type),但是在传输时将它们转换为小写字母(如content-type)。

头字段名只能由以下一个或多个ASCII字符组成:a-zA-Z0-9!#$%&'*+-, .^_`|、 和~

在HTTP标头字段名称中使用无效字符将导致流关闭,并报告协议错误。

头字段的值处理比较宽松,但不应包含换行符或回车符,并且应根据HTTP规范的要求仅限使用US-ASCII字符。


1.22 在客户端推送流

要在客户端上接收推送的流,需要在ClientHttp2Session上为'stream'事件设置一个监听器:

const http2 = require('http2');

const client = http2.connect('http://localhost');

client.on('stream', (pushedStream, requestHeaders) => {
  pushedStream.on('push', (responseHeaders) => {
    // process response headers
  });
  pushedStream.on('data', (chunk) => { /* handle pushed data */ });
});

const req = client.request({ ':path': '/' });


1.23 支持CONNECT方法

CONNECT方法用于在 HTTP/2 服务器中允许做为 TCP/IP 连接代理。一个简单的TCP服务器:

const net = require('net');

const server = net.createServer((socket) => {
  let name = '';
  socket.setEncoding('utf8');
  socket.on('data', (chunk) => name += chunk);
  socket.on('end', () => socket.end(`hello ${name}`));
});

server.listen(8000);

一个HTTP/2 CONNECT代理:

const http2 = require('http2');
const { NGHTTP2_REFUSED_STREAM } = http2.constants;
const net = require('net');

const proxy = http2.createServer();
proxy.on('stream', (stream, headers) => {
  if (headers[':method'] !== 'CONNECT') {
    // Only accept CONNECT requests
    stream.close(NGHTTP2_REFUSED_STREAM);
    return;
  }
  const auth = new URL(`tcp://${headers[':authority']}`);
  // It's a very good idea to verify that hostname and port are
  // things this proxy should be connecting to.
  const socket = net.connect(auth.port, auth.hostname, () => {
    stream.respond();
    socket.pipe(stream);
    stream.pipe(socket);
  });
  socket.on('error', (error) => {
    stream.close(http2.constants.NGHTTP2_CONNECT_ERROR);
  });
});

proxy.listen(8001);

一个HTTP/2 CONNECT客户端:

const http2 = require('http2');

const client = http2.connect('http://localhost:8001');

// Must not specify the ':path' and ':scheme' headers
// for CONNECT requests or an error will be thrown.
const req = client.request({
  ':method': 'CONNECT',
  ':authority': `localhost:${port}`
});

req.on('response', (headers) => {
  console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
});
let data = '';
req.setEncoding('utf8');
req.on('data', (chunk) => data += chunk);
req.on('end', () => {
  console.log(`The server says: ${data}`);
  client.close();
});
req.end('Jane');


1.24 扩展CONNECT协议

RFC 定义了 HTTP/2 “扩展CONNECT协议”("Extended CONNECT Protocol")扩展,可用于使用CONNECT方法作为其他通信协议(如WebSockets)的隧道来使用Http2Stream

HTTP/2 服务器通过enableConnectProtocol设置启用扩展CONNECT协议:

const http2 = require('http2');
const settings = { enableConnectProtocol: true };
const server = http2.createServer({ settings });

当客户端从服务器收到SETTINGS帧时,就表示可以使用扩展的CONNECT,它就可以发送使用':protocol' HTTP/2 伪标头的CONNECT请求:

const http2 = require('http2');
const client = http2.connect('http://localhost:8080');
client.on('remoteSettings', (settings) => {
  if (settings.enableConnectProtocol) {
    const req = client.request({ ':method': 'CONNECT', ':protocol': 'foo' });
    // ...
  }
});


2. 兼容性API

兼容API的设置目标是在 HTTP/2 中向开发人员提供类似 HTTP/1 的开发体验,从而可以开发支持 HTTP/1 和 HTTP/2 的应用程序。此API仅针对 HTTP/1 的公共API。但是,许多模块使用内部方法或状态,并且不支持这些模块,因为它们的实现不同。

以下是一个使用兼容API创建 HTTP/2 服务器的示例:

const http2 = require('http2');
const server = http2.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Foo', 'bar');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
});

要创建 HTTPS 和 HTTP/2 混合服务器,请参阅ALPN 协商部分。不支持从非tls HTTP/1 服务器升级。

HTTP/2 兼容API由Http2ServerRequestHttp2ServerResponse组成。它们的设计目标是提供与 HTTP/1 兼容的API,但并不隐藏协议之间的差异。如,忽略HTTP状态码的状态消息。


2.1 ALPN 协商

ALPN 协商允许通过同一套接字支持 HTTPS 和 HTTP/2。reqres对象可以是 HTTP/1 或 HTTP/2,应用程序必须将自身限制为 HTTP/1 的公共API,并检测是否可以使用 HTTP/2 的更高级特性。

以下一个创建支持两种协议服务器的示例:

const { createSecureServer } = require('http2');
const { readFileSync } = require('fs');

const cert = readFileSync('./cert.pem');
const key = readFileSync('./key.pem');

const server = createSecureServer(
  { cert, key, allowHTTP1: true },
  onRequest
).listen(4443);

function onRequest(req, res) {
  // detects if it is a HTTPS request or HTTP/2
  const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ?
    req.stream.session : req;
  res.writeHead(200, { 'content-type': 'application/json' });
  res.end(JSON.stringify({
    alpnProtocol,
    httpVersion: req.httpVersion
  }));
}

以上示例中'request'事件在 HTTPS 和 HTTP/2 上的工作方式相同。


2.2 Class: http2.Http2ServerRequest

Http2ServerRequest对象由http2.Serverhttp2.SecureServer创建,并作为第一个参数传递给'request'事件。可用于访问请求状态,标头和数据。

它实现了Readable Stream接口,以及以下附加事件,方法和属性。


2.2.1 Event: 'aborted'

每当Http2ServerRequest实例在通信中异常中止时,就会发出'aborted'事件。

只有在Http2ServerRequest可写端尚未结束时才会发出'aborted'事件。


2.2.2 Event: 'close'

表示底层Http2Stream已关闭。像'end'一样,每个响应只发生一次此事件。


2.2.3 request.aborted 属性

  • <boolean>

当请求已中止时,则request.aborted属性为true


2.2.4 request.destroy([error])

  • error <Error>

在接收Http2ServerRequestHttp2Stream上调用destroy()。如果提供了error,则会发出'error'事件,并将error作为参数传递给事件上的任何侦听器。

如果流已经被销毁,则什么都不做。


2.2.5 request.headers 属性

  • <Object>

request/response 的标头对象

标头键/值对的名称和值,其中名称是小写格式:

// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
//   host: '127.0.0.1:8000',
//   accept: '*/*' }
console.log(request.headers);

在 HTTP/2 中,请求路径、主机名、协议和方法表示为前缀为:的特殊标头(如':path')。这些特殊标头将包含在request.headers对象中。请注意无意中修改这些特殊标头或可能发生错误。如,从请求中删除所有请求会引发错误:

removeAllHeaders(request.headers);
assert(request.url);   // Fails because the :path header has been removed


2.2.6 request.httpVersion 属性

  • <string>

在服务器请求的情况下,客户端发送的HTTP版本。在客户端响应的情况下,连接到的服务器使用的HTTP版本。返回:'2.0'

另外message.httpVersionMajor是第一个整数,message.httpVersionMinor是第二个。


2.2.7 request.method 属性

  • <string>

字符串格式的请求方法。只读。如:'GET''DELETE'


2.2.8 request.rawHeaders 属性

  • <string[]>

原始 request/response 标头列表与收到的完全一致。

注意,键和值位于同一列表中。它不是元组列表。因此,偶数偏移是键名,奇数偏移是关联值。

标题名称不是小写的,且不会合并重复项。

// Prints something like:
//
// [ 'user-agent',
//   'this is invalid because there can be only one',
//   'User-Agent',
//   'curl/7.22.0',
//   'Host',
//   '127.0.0.1:8000',
//   'ACCEPT',
//   '*/*' ]
console.log(request.rawHeaders);


2.2.9 request.rawTrailers 属性

  • <string[]>

原始 request/response 预告的键和值与收到的完全相同。仅在'end'事件中填充。


2.2.10 request.setTimeout(msecs, callback)

设置 Http2Stream 的超时时间为msecs。如果提供了callback,则会将其作为临听器添加到响应对象上的'timeout'事件中。

如果没有向请求、响应或服务器添加'timeout'侦听器,则Http2Streams在超时时将被销毁。如果添加了,则必须明确处理超时套接字。


2.2.11 request.socket 属性

  • <net.Socket>|<tls.TLSSocket>

返回充当net.Socket(或tls.TLSSocket)的Proxy对象,但应用基于 HTTP/2 逻辑的getter,setter和方法。

将从request.stream中检索并设置destroyedreadablewritable属性。

destroyedemitendononce方法会在request.stream上调用。

setTimeout方法会在request.stream.session上调用

pausereadresumewrite

将使用ERR_HTTP2_NO_SOCKET_MANIPULATION代码引发错误。见Http2Session 和 Sockets

所有其他交互将直接路由到套接字。在TLS支持下,使用request.socket.getPeerCertificate()来获取客户端的身份验证详细信息。


2.2.12 request.stream 属性

  • <Http2Stream>

支持请求的Http2Stream对象。


2.2.13 request.trailers 属性

  • <Object>

request/response 预告对象。仅在'end'事件中填充。


2.2.14 request.url 属性

  • <string>

请求URL字符串。它仅包含实际HTTP请求中存在的URL。如果请求是:

GET /status?name=ryan HTTP/1.1\r\n
Accept: text/plain\r\n
\r\n

request.url将是:

'/status?name=ryan'

解析URL的部分可以使用require('url').parse(request.url)

$ node
> require('url').parse('/status?name=ryan')
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=ryan',
  query: 'name=ryan',
  pathname: '/status',
  path: '/status?name=ryan',
  href: '/status?name=ryan' }

获取查询字符串中的参数,可以使用require('querystring').parseparse函数,或者可以将true作为第二个参数传递给require('url').parse

$ node
> require('url').parse('/status?name=ryan', true)
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=ryan',
  query: { name: 'ryan' },
  pathname: '/status',
  path: '/status?name=ryan',
  href: '/status?name=ryan' }


2.3 Class: http2.Http2ServerResponse

本对象由HTTP服务器在内部创建,而不是用户创建。它作为第二个参数传递给'request'事件。

响应继承自Stream,并另外实现了以下内容:


2.3.1 Event: 'close'

表示在调用response.end()或能够刷新之前终止了底层Http2Stream。


2.3.2 Event: 'finish'

响应发送后发出。即:当响应头和主体的最后一段已经切换到 HTTP/2 多路复用以通过网络传输时,发出该事件。这并不意味着客户端收到了任何信息。

在此事件之后,将不会在响应对象上发出事件。


2.3.3 response.addTrailers(headers)

  • headers <Object>

此方法将 HTTP 尾随标头(标头但在消息末尾)添加到响应中。设置中包含无效字符的标头字段名称或值将导致抛出TypeError。


2.3.4 response.connection 属性

  • <net.Socket>|<tls.TLSSocket>


2.3.5 response.end([data][, encoding][, callback])

  • data <string>|<Buffer>
  • encoding <string>
  • callback <Function>
  • 返回:this

向服务器发信号,表明已发送所有响应标头和正文; 服务器应该考虑此消息完成,必须在每个响应上调用response.end()方法。

如果指定了data,则相当于调用response.write(data,encoding),然后调用response.end(callback)。如果指定了callback,则会在响应流完成时调用它。


2.3.6 response.finished 属性

  • <boolean>

指示响应是否已完成。初始状态为false,在response.end()调用之后,该值将为true


2.3.7 response.getHeader(name)

  • name <string>
  • 返回: <string>

读出已排队但未发送到客户端的标头。不区分大小写。

const contentType = response.getHeader('content-type');


2.3.8 response.getHeaderNames()

  • 返回:<string[]>

返回一个数组,其中包含当前传出标头的唯一名称。所有标题名称都是小写的。

response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);

const headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']


2.3.9 response.getHeaders()

  • 返回:<Object>

返回当前传出标头的浅复制副本。由于使用浅复制,因此数组值可以修改而无需额外调用各种与头相关的http模块方法。返回对象的键是标头名称,值是各自标头值。所有标题名称都是小写的。

response.getHeaders()方法返回的对象不是原型继承自JavaScript Object。这意味着没有典型的Object方法,如:obj.toString()obj.hasOwnProperty()等并且不起作用。

response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);

const headers = response.getHeaders();
// headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }


2.3.10 response.hasHeader(name)

  • name <string>
  • 返回:<Object>

如果当前在传出标头中设置了由name标识的标头,则返回true。名称不区分大小写。

const hasContentType = response.hasHeader('content-type');


2.3.11 response.headersSent 属性

  • <boolean>

标头已发出则为true,否则false。只读


2.3.12 response.removeHeader(name)

  • name <string>

删除已排队待发送的标头。

response.removeHeader('Content-Encoding');


2.3.13 response.sendDate 属性

  • <boolean>

如果为true,则Date标头将自动生成并在响应中发送(如果标头中尚不存在)。默认为true


2.3.15 response.setHeader(name, value)

  • name <string>
  • value <string>|<string[]>

设置单个标头值。如果此标头已存在于待发送标头中,则其值将被替换。当发送多个标头时,可以向value中传入一个字符串数组。

response.setHeader('Content-Type', 'text/html');

response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);

设置包含无效字符的标头字段名称或值将导致抛出TypeError。

当使用response.setHeader()设置标头时,它们将与传递给response.writeHead()的任何标头合并,并将标头传递给response.writeHead指定优先级。

// returns content-type = text/plain
const server = http2.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Foo', 'bar');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
});


2.3.16 response.setTimeout(msecs[, callback])

  • msecs <number>
  • callback <Function>
  • 返回:<http2.Http2ServerResponse>

设置Http2Stream的超时时间msecs。如果提供了callback,则会将其作为监听器添加到响应对象上的'timeout'事件中。

如果没有向请求、响应或服务器添加'timeout'监听器,则Http2Stream在超时时将被销毁。如果为请求、响应或服务器的'timeout'事件分配了处理程序,则必须明确处理超时套接字。


2.3.17 response.socket 属性

  • <net.Socket>|<tls.TLSSocket>

返回充当net.Socket(或tls.TLSSocket)的Proxy对象,但应用基于 HTTP/2 逻辑的getter,setter和方法。

将从response.stream中检索并设置destroyedreadablewritable属性。

destroyedemitendononce方法会在response.stream上调用。

setTimeout方法会在response.stream.session上调用

pausereadresumewrite

将使用ERR_HTTP2_NO_SOCKET_MANIPULATION代码引发错误。见Http2Session 和 Sockets

所有其他交互将直接路由到套接字。

const http2 = require('http2');
const server = http2.createServer((req, res) => {
  const ip = req.socket.remoteAddress;
  const port = req.socket.remotePort;
  res.end(`Your IP address is ${ip} and your source port is ${port}.`);
}).listen(3000);


2.3.18 response.statusCode 属性

  • <number>

使用隐式标头(不显式调用response.writeHead())时,此属性控制在刷新标头时将发送到客户端的状态代码。

response.statusCode = 404;

响应头发送到客户端后,此属性指示已发送的状态代码。


2.3.19 response.statusMessage 属性

  • <string>

状态消息。HTTP/2(RFC7540 8.1.2.4)不支持状态消息。返回一个空字符串。


2.3.20 response.stream 属性

支持响应的Http2Stream对象。


2.3.21 response.write(chunk[, encoding][, callback])

  • chunk <string>|<Buffer>
  • encoding <string>
  • callback <Function>
  • 返回:<boolean>

调用本方法且尚未调用response.writeHead(),则将切换到隐式标头模式并刷新隐式标头。

这会发送一块响应主体。可以多次调用本方法完成响应体的连续发送。

需要注意,在http模块中,当请求是HEAD请求时,将省略响应正文。同样,204304响应也不得包含消息正文。

chunk可以是字符串或缓冲区。如果是字符串,则第二个参数指定如何将其编码为字节流。默认情况下encoding'utf8'。刷新此数据块时将调用callback

这是原始HTTP响应体,与可能使用的更高级别的多部分正文编码无关。

第一次调用response.write()时,它会将缓冲的头信息和正文的第一个块发送给客户端。第二次调用response.write()时,Node.js假定数据将被流式传输,并分别发送新数据。也就是说,response 被缓冲到响应体的第一块。

整个数据成功刷新到内核缓冲区,则返回true。如果全部或部分数据在用户内存中排队,则返z回false。当缓冲区再次空闲时,将发出'drain'


2.3.22 response.writeContinue()

向客户端发送一个100 Continue响应,表示客户端应发送请求正文。请参阅Http2ServerHttp2SecureServer上的'checkContinue'事件。


2.3.23 response.writeHead(statusCode[, statusMessage][, headers])

  • statusCode <number>
  • statusMessage <string>
  • headers <Object>

向请求方发送一个响应头。状态码(statusCode)应该是一个3位的表示HTTP状态的整数,如404。最后的headers是响应头对象。

为了与 HTTP/1 兼容,可以将人类可读的statusMessage作为第二个参数传递。但是,因为statusMessage在 HTTP/2 中没有意义,所以该参数将不起作用并且将发出进程警告。

const body = 'hello world';
response.writeHead(200, {
  'Content-Length': Buffer.byteLength(body),
  'Content-Type': 'text/plain' });

在调用response.end()之前,可以在消息上最多调用此方法一次。

如果在调用本方法之前调用了response.write()response.end(),则将计算隐式/可变标头并调用此函数。

当使用response.setHeader()设置标头时,它们将与传递给response.writeHead()的任何标头合并,并指定优先级。

// returns content-type = text/plain
const server = http2.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Foo', 'bar');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
});

设置标头字段名称或值时,如果包含无效字符,将导致抛出TypeError。


2.3.24 response.createPushResponse(headers, callback)

  • headers <HTTP/2 Headers Object> 一个响应标头描述对象
  • callback <Function> 一旦http2stream.pushStream()完成,或者在创建推送的Http2Stream的尝试失败(或被拒绝时)调用,或者在调用http2stream.pushStream()方法之前关闭Http2ServerRequest的状态。其包含以下两个回调参数:

使用指定标头调用http2stream.pushStream(),并在新创建的Http2ServerResponse上将指定的Http2Stream包装为回调参数(如果成功)。关闭Http2ServerRequest时,将调用回调,并传入ERR_HTTP2_INVALID_STREAM错误。


HTTP/2 性能指标收集

自Node.js V8.5版本起,增加了Performance Timing API,提供了W3C Performance Timeline规范的实现,目的在于是支持高分辨率性能指标的收集。其中的Performance Observer API可用于可收集每个Http2SessionHttp2Stream实例的基本性能指标。

const { PerformanceObserver } = require('perf_hooks');

const obs = new PerformanceObserver((items) => {
  const entry = items.getEntries()[0];
  console.log(entry.entryType);  // prints 'http2'
  if (entry.name === 'Http2Session') {
    // entry contains statistics about the Http2Session
  } else if (entry.name === 'Http2Stream') {
    // entry contains statistics about the Http2Stream
  }
});
obs.observe({ entryTypes: ['http2'] });

其中,PerformanceEntryentryType属性等于'http2'

PerformanceEntryname属性等于'Http2Stream''Http2Session'

name属性等于'Http2Stream'时,PerformanceEntry还包括以下额外属性:

  • bytesRead <number> 当前Http2Stream收到DATA帧的字节数
  • bytesWritten <number>当前Http2Stream发送DATA帧的字节数
  • id <number> 所关联的Http2Stream的标识符
  • timeToFirstByte <number> PerformanceEntrystartTime到收到第一个DATA帧之间经过的毫秒数。
  • timeToFirstByteSent <number> PerformanceEntrystartTime到发送第一个DATA帧之间经过的毫秒数。
  • timeToFirstHeader <number> PerformanceEntrystartTime到收到第一个标头之间经过的毫秒数。


name属性等于'Http2Session'时,PerformanceEntry还包括以下额外属性:

  • bytesRead <number> 当前Http2Session接收的字节数
  • bytesWritten <number> 当前Http2Session发送的字节数
  • framesReceived <number> 当前Http2Session接收的 HTTP/2 帧数
  • framesSent <number> 当前Http2Session发送的 HTTP/2 帧数
  • maxConcurrentStreams <number> Http2Session的生命周期内同时打开的最大流数
  • pingRTT <number> 自PING帧传输到接收确认后经过的毫秒数。仅在Http2Session上发送PING帧时才出现。
  • streamAverageDuration <number> 所有Http2Stream实例的平均持续时间(以毫秒为单位)。
  • streamCount <number> Http2Session处理的Http2Stream实例数。
  • type <string> Http2Session的类型标识,其值为'server''client'