http2
模块是自Node.jsv8.4.0
起添加的一个核心模块,它主要提供了对HTTP/2协议的实现。
- 核心API
- 1.1 使用示例
- 1.2 Class: Http2Session
- 1.3 Class: ServerHttp2Session
- 1.4 Class: ClientHttp2Session
- 1.5 Class: Http2Stream
- 1.6 Class: ClientHttp2Stream
- 1.7 Class: ServerHttp2Stream
- 1.8 Class: Http2Server
- 1.9 Class: Http2SecureServer
- 1.10 http2.createServer(options[, onRequestHandler])
- 1.11 http2.createSecureServer(options[, onRequestHandler])
- 1.12 http2.connect(authority[, options][, listener])
- 1.13 http2.constants 属性
- 1.14 http2.getDefaultSettings()
- 1.15 http2.getPackedSettings(settings)
- 1.16 http2.getUnpackedSettings(buf)
- 1.17 Headers 对象
- 1.18 设置对象
- 1.19 使用
`options.selectPadding()`
- 1.20 错误处理
- 1.21 标头字段名和值中的无效字符处理
- 1.22 在客户端推送流
- 1.23 支持CONNECT方法
- 1.24 扩展CONNECT协议
- 兼容API
- 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
对象,大多数操作是通过与<Http2Server
或Http2Stream
对象的交互来完成。
1.2.1 Http2Session与Socket
每个Http2Session
实例在创建时都会与一个net.Socket
或tls.TLSSocket
相关联。当Socket
或Http2Session
被销毁时,两者都将被销毁。
由于 HTTP/2 协议强制要求的指定序列化及处理要求,不建议用户代码从Http2Session
所绑定的Socket
实例读取或写入数据。这样会使 HTTP/2 会话进入不确定状态,从而导致会话和套接字变得不可用。
一旦Socket
绑定到Http2Session
,用户代码应该仅使用Http2Session
的API。
1.2.2 Http2Session中的事件
- Event: 'close'
- Event: 'connect'
- Event: 'error'
- Event: 'frameError'
- Event: 'goaway'
- Event: 'localSettings'
- Event: 'remoteSettings'
- Event: 'stream'
- Event: 'timeout'
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'
事件回调函数参数如下:
settings
<HTTP/2 Settings Object>所收到的SETTINGS
帧的副本
Event: 'remoteSettings'
当从所连接的对等方接收到新的SETTINGS
帧时,将发出'remoteSettings'
事件。
session.on('remoteSettings', (settings) => { /* 使用新设置 */ });
'remoteSettings'
事件回调函数参数如下:
settings
<HTTP/2 Settings Object>所收到的SETTINGS
帧的副本
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.Server
或tls.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.Socket
或tls.TLSSocket
被销毁后,Http2Session
会发出'close'
事件。如果error
不是未定义,则会在'close'
事件之前发出'error'
事件。
如果有任何与Http2Session
相关联的已打开的Http2Stream
,其也会将被销毁。
1.2.8 http2session.destroyed 属性
- <boolean>
如果为true
则Http2Session
实例已被销毁且不能再使用,否则为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>TypedArray
或DataView
实例,包含要在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
成功确认将为null
;duration
-报告自发送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 的安全方法。
destroy
、emit
、end
、pause
、read
、resume
、write
将使用触发错误代码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 aWINDOW_UPDATE
.lastProcStreamID
<number>Http2Stream
的数字ID,可能是最近收到的HEADERS
或DATA
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>当为true
和parent
标识一个父流时,创建的流将成为父项的唯一直接依赖项,所有其他现有依赖项将依赖于新创建的流。默认false
parent
<number>指定新创建的流所依赖的流的数字标识符。weight
<number>指定流相对于具有相同parent
的其他流的相对依赖性。其取值范围为1
到256
(包含)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
类是ServerHttp2Stream和ClientHttp2Stream类的基础,每个类分别由服务器端或客户端使用。
所有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
属性会设置为true
,http2stream.rstCode
会被设置为具体的错误码。Http2Stream
实例也不再可用。
1.5.2 Http2Stream中的事件
- Event: 'aborted'
- Event: 'close'
- Event: 'error'
- Event: 'frameError'
- Event: 'timeout'
- Event: 'trailers'
- Event: 'wantTrailers'
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> 当为true
且parent
标识父Stream时,此流将为父对象的唯一直接依赖关系。默认为false
parent
- <number> 指定此流所依赖的流的数字标识符weight
- <number> 指定流相对于具有相同父级的其他流的相对依赖性。取值范围为1
到256
(含)之间的数字silent
- <boolean> 如果为true
,则在本地更改优先级,而不向连接的对等端发送PRIORITY
帧。
更新此Http2Stream
实例的优先级。
1.5.10 http2stream.rstCode 属性
- <number>
设置为在从连接的对等方接收RST_STREAM
帧时,调用http2stream.close()
或http2stream.destroy()
销毁Http2Stream
时所报告的RST_STREA
M错误代码。如果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 属性
对拥有此Http2Stream
的Http2Session
实例的引用。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
- Extends<Http2Stream>
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
- Extends<Http2Stream>
ServerHttp2Stream
类同样是对Http2Stream
的扩展,专用于 HTTP/2 服务器端。会在服务器上提供相关方法,如http2stream.pushStream()
、http2stream.respond()
等。
1.7.1 http2stream.additionalHeaders(headers)
headers
<HTTP/2 Headers Object>
向连接的 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>当为true
和parent
标识一个父流时,创建的流将成为父项的唯一直接依赖项,所有其他现有依赖项将依赖于新创建的流。默认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.waitForTrailers
,Http2Stream
在传输最终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()
调用以收集所提供的文件描述符的详细信息。
offset
和length
选项可用于限制对指定范围子集进行响应。
文件描述符不会随流的关闭而关闭,所以需要在不使用后手工将其关闭。注意,不支持同时为多个流使用相同的文件描述符,这可能会导致数据丢失。在流完成后可以重新使用文件描述符。
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
头会自动设置。
offset
和length
选项可用于限制对指定范围子集进行响应。
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'
- Event: 'request'
- Event: 'session'
- Event: 'sessionError'
- Event: 'stream'
- Event: 'timeout'
Event: 'checkContinue'
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
如果已注册'request'
监听器或http2.createServer()提供了回调函数,'checkContinue'
事件会在每次收到HTTP Expect: 100-continue
请求时发出。如果未添加事件监听器,服务器会自动响应100 Continue
状态。
处理此事需要调用response.writeContinue(),如果客户端应继续发送请求体,或者如果客户端不应继续发送请求体,则生成适当的HTTP响应(如:400 Bad Request)。
需要注意,发出和处理此事件时,不会发出'request'
事件。
Event: 'request'
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
每次有请求时都会发出本事件。需要注意,每个会话都可能会有多个请求。请参阅兼容性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>
类似于Http2Server
,Http2SecureServer
的实例使用http2.createSecureServer()
函数创建的。http2
模块同样没有直接导出Http2SecureServer
类。
1.9.1 Http2SecureServer中的事件
- Event: 'checkContinue'
- Event: 'request'
- Event: 'session'
- Event: 'sessionError'
- Event: 'stream'
- Event: 'timeout'
- Event: 'unknownProtocol'
Event: 'checkContinue'
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
如果注册了'request'
监听器或者为http2.createSecureServer()
提供了回调函数,则每次收到HTTP Expect:100-continue
状态的请求时都会发出'checkContinue'
事件。如果监听此事件,则服务器将自动响应100 Continue
状态。
处理此事需要调用response.writeContinue(),如果客户端应继续发送请求体,或者如果客户端不应继续发送请求体,则生成适当的HTTP响应(如:400 Bad Request)。
需要注意,发出和处理此事件时,不会发出'request'
事件。
Event: 'request'
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
每次有请求时都会发出本事件。需要注意,每个会话都可能会有多个请求。请参阅兼容性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
会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。maxHeaderListPairs
<number> 设置标头条目的最大数量。最小值是4
。默认:128
。maxOutstandingPings
<number> 设置未完成的、未确认的 ping 数量。默认:10
。maxSendHeaderBlockLength
<number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'
事件并关闭和销毁流。paddingStrategy
<number> 标识用于确定用于HEADERS
和DATA
帧的填充量的策略。默认: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
会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。默认:10
。maxHeaderListPairs
<number> 设置标头条目的最大数量。最小值是4
。默认:128
。maxOutstandingPings
<number> 设置未完成的、未确认的 ping 数量。默认:10
。maxSendHeaderBlockLength
<number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'
事件并关闭和销毁流。paddingStrategy
<number> 标识用于确定用于HEADERS
和DATA
帧的填充量的策略。默认: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()
选项都可以提供。对于服务器来说,通常需要标识选项(pfx
或key
/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
会话的数量、报头压缩表的当前内存使用、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。默认:10
。maxHeaderListPairs
<number> 设置标头条目的最大数量。最小值是4
。默认:128
。maxOutstandingPings
<number> 设置未完成的、未确认的 ping 数量。默认:10
。maxReservedRemoteStreams
<number> 设置客户端在指定时间可接受的最大保留推送流数。一旦当前保留的推送流的数量超过此限制,服务器发送的新推送流将被自动拒绝。maxSendHeaderBlockLength
<number>设置序列化压缩标头块的最大允许大小。尝试发送超过此限制的标头将导致发出'frameError'
事件并关闭和销毁流。paddingStrategy
<number> 标识用于确定用于HEADERS
和DATA
帧的填充量的策略。默认: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> 一个可选的回调函数,它接收传递给connect
和options
对象的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的错误码:
值 | 代码名 | 常量 |
---|---|---|
0x00 | No Error | http2.constants.NGHTTP2_NO_ERROR |
0x01 | Protocol Error | http2.constants.NGHTTP2_PROTOCOL_ERROR |
0x02 | Internal Error | http2.constants.NGHTTP2_INTERNAL_ERROR |
0x03 | Flow Control Error | http2.constants.NGHTTP2_FLOW_CONTROL_ERROR |
0x04 | Settings Timeout | http2.constants.NGHTTP2_SETTINGS_TIMEOUT |
0x05 | Stream Closed | http2.constants.NGHTTP2_STREAM_CLOSED |
0x06 | Frame Size Error | http2.constants.NGHTTP2_FRAME_SIZE_ERROR |
0x07 | Refused Stream | http2.constants.NGHTTP2_REFUSED_STREAM |
0x08 | Cancel | http2.constants.NGHTTP2_CANCEL |
0x09 | Compression Error | http2.constants.NGHTTP2_COMPRESSION_ERROR |
0x0a | Connect Error | http2.constants.NGHTTP2_CONNECT_ERROR |
0x0b | Enhance Your Calm | http2.constants.NGHTTP2_ENHANCE_YOUR_CALM |
0x0c | Inadequate Security | http2.constants.NGHTTP2_INADEQUATE_SECURITY |
0x0d | HTTP/1.1 Required | http2.constants.NGHTTP2_HTTP_1_1_REQUIRED |
使用http2server.setTimeout()
设置毫秒数时,服务器在指定时间内没有活动时会发出'timeout'
事件。
1.14 http2.getDefaultSettings()
返回包含ttp2Session
H实例的默认设置的对象。每次调用此方法时,此方法都会返回一个新对象实例,因此可以安全地修改所返回的实例以供使用。
1.15 http2.getPackedSettings(settings)
settings
<HTTP/2 Settings Object>- 返回:<Buffer>
返回一个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)
buf
<Buffer>|<Uint8Array> 包设置- 返回:<HTTP/2 Settings Object>
返回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
、:protocol
、age
、authorization
、access-control-allow-credentials
、access-control-max-age
、access-control-request-method
、content-encoding
、content-language
、content-length
、content-location
、content-md5
、content-range
、content-type
、date
、dnt
、etag
、expires
、from
、if-match
、if-modified-since
、if-none-match
、if-range
、if-unmodified-since
、last-modified
,location
、max-forwards
,proxy-authorization
、range
、referer
,retry-after
、tk
、upgrade-insecure-requests
、user-agent
或x-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.localSettings
和
http2session.remoteSettings
API作为输入返回或接收定义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()
回调函数(如果提供),以确定每个HEADERS
和DATA
帧使用的特定填充量。
options.selectPadding()
函数接收两个数字参数frameLen
和maxFrameLen
,并且必须返回一个数字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()
函数为每个HEADERS
和DATA
帧调用一次。这会对性能有明显的影响。
1.20 错误处理
使用http2
模块时可能会出现几种类型的错误情况:
- 传入不正确的参数、选项或设置值时会发生验证错误。这些错误始终由同步
throw
报告。 - 在不正确的时间尝试操作时发生状态错误(如,尝试在关闭后在流上发送数据)。这些将使用
Http2Stream
、Http2Session
或 HTTP/2 Server 对象上的同步throw
或'error'
事件进行报告,具体取决于错误发生的位置和时间。 - HTTP/2 会话意外失败时发生内部错误。这些将通过
Http2Session
或 HTTP/2 服务器对象上的'error'
事件进行报告。 - 当违反 HTTP/2 各种协议约束时,会发生协议错误。这些将使用
Http2Stream
、Http2Session
或 HTTP/2 Server 对象上的同步throw
或'error'
事件进行报告,具体取决于错误发生的位置和时间。
1.21 标头字段名和值中的无效字符处理
与 HTTP/1 的实现相比,HTTP/2 在HTTP头名称和值中应更严格的对无效字符进行处理。
标题字段名称不区分大小写,并严格地作为小写字符串进行传输。Node.js提供的API允许标题名称被设置为混合大小写字符串(如Content-Type
),但是在传输时将它们转换为小写字母(如content-type
)。
头字段名只能由以下一个或多个ASCII字符组成:a
-z
、A
-Z
、0
-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由Http2ServerRequest
和Http2ServerResponse
组成。它们的设计目标是提供与 HTTP/1 兼容的API,但并不隐藏协议之间的差异。如,忽略HTTP状态码的状态消息。
2.1 ALPN 协商
ALPN 协商允许通过同一套接字支持 HTTPS 和 HTTP/2。req
和res
对象可以是 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.Server
或http2.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>
在接收Http2ServerRequest
的Http2Stream
上调用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)
msecs
<number>callback
<Function>- 返回:<http2.Http2ServerRequest>
设置 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
中检索并设置destroyed
、readable
和writable
属性。
destroyed
、emit
、end
、on
和once
方法会在request.stream
上调用。
setTimeout
方法会在request.stream.session
上调用
pause
、read
、resume
和write
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').parse
parse函数,或者可以将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()/code>等并且不起作用。
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
中检索并设置destroyed
、readable
和writable
属性。
destroyed
、emit
、end
、on
和once
方法会在response.stream
上调用。
setTimeout
方法会在response.stream.session
上调用
pause
、read
、resume
和write
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
请求时,将省略响应正文。同样,204
和304
响应也不得包含消息正文。
chunk
可以是字符串或缓冲区。如果是字符串,则第二个参数指定如何将其编码为字节流。默认情况下encoding
是'utf8'
。刷新此数据块时将调用callback
。
这是原始HTTP响应体,与可能使用的更高级别的多部分正文编码无关。
第一次调用response.write()时,它会将缓冲的头信息和正文的第一个块发送给客户端。第二次调用response.write()时,Node.js假定数据将被流式传输,并分别发送新数据。也就是说,response 被缓冲到响应体的第一块。
整个数据成功刷新到内核缓冲区,则返回true
。如果全部或部分数据在用户内存中排队,则返z回false
。当缓冲区再次空闲时,将发出'drain'
。
2.3.22 response.writeContinue()
向客户端发送一个100 Continue
响应,表示客户端应发送请求正文。请参阅Http2Server
和Http2SecureServer
上的'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
的状态。其包含以下两个回调参数:err
<Error>headers
<ServerHttp2Stream> 一个响应标头描述对象
使用指定标头调用http2stream.pushStream()
,并在新创建的Http2ServerResponse
上将指定的Http2Stream
包装为回调参数(如果成功)。关闭Http2ServerRequest
时,将调用回调,并传入ERR_HTTP2_INVALID_STREAM
错误。
HTTP/2 性能指标收集
自Node.js V8.5版本起,增加了Performance Timing API,提供了W3C Performance Timeline规范的实现,目的在于是支持高分辨率性能指标的收集。其中的Performance Observer API可用于可收集每个Http2Session和Http2Stream实例的基本性能指标。
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'] });
其中,PerformanceEntry
的entryType
属性等于'http2'
。
PerformanceEntry
的name
属性等于'Http2Stream'
或'Http2Session'
。
当name
属性等于'Http2Stream'
时,PerformanceEntry
还包括以下额外属性:
bytesRead
<number> 当前Http2Stream
收到DATA
帧的字节数bytesWritten
<number>当前Http2Stream
发送DATA
帧的字节数id
<number> 所关联的Http2Stream
的标识符timeToFirstByte
<number>PerformanceEntry
的startTime
到收到第一个DATA
帧之间经过的毫秒数。timeToFirstByteSent
<number>PerformanceEntry
的startTime
到发送第一个DATA
帧之间经过的毫秒数。timeToFirstHeader
<number>PerformanceEntry
的startTime
到收到第一个标头之间经过的毫秒数。
当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'