关于 Node.js v12.16.2 中 HTTP/2 的支持
Node.js v12.16.2 提供了对 HTTP/2 协议的支持,通过内置模块 http2
实现。此模块允许开发者创建基于 HTTP/2 的服务器和客户端应用程序。
以下是使用 http2
创建简单 HTTP/2 服务器的代码示例:
const http2 = require('http2');
// 创建 HTTP/2 服务器
const server = http2.createSecureServer({
key: fs.readFileSync('/path/to/key.pem'), // 替换为实际路径
cert: fs.readFileSync('/path/to/cert.pem') // 替换为实际路径
}, (stream, headers) => {
stream.respond({
'content-type': 'text/plain',
':status': 200
});
stream.end('Hello World!');
});
server.listen(8080);
console.log(`HTTP/2 Server running at https://localhost:8080`);
需要注意的是,在启用 HTTP/2 支持时,必须提供有效的 SSL/TLS 密钥和证书文件,因为 HTTP/2 要求连接必须加密。
此外,Node.js 文档还提到某些情况下可能因 OpenSSL 库的原因引发错误,例如 PBKDF2 算法失败的情况。尽管这些错误通常不直接影响 HTTP/2 功能,但在配置 HTTPS 或 TLS 设置时仍需注意潜在问题。
特性和限制
-
特性: HTTP/2 增强了性能表现,引入多路复用、头部压缩以及服务端推送等功能。
-
限制: 需要确保运行环境支持最新的 OpenSSL 版本,并且开发人员应熟悉如何处理安全上下文中的密钥管理。
Node.js v12.16.2 Documentation HTTP/2
Index View on single page View as JSON View another version ▼Edit on GitHub
Table of Contents
HTTP/2
Core API
Server-side example
Client-side example
Class: Http2Session
Http2Session and Sockets
Event: 'close'
Event: 'connect'
Event: 'error'
Event: 'frameError'
Event: 'goaway'
Event: 'localSettings'
Event: 'ping'
Event: 'remoteSettings'
Event: 'stream'
Event: 'timeout'
http2session.alpnProtocol
http2session.close([callback])
http2session.closed
http2session.connecting
http2session.destroy([error][, code])
http2session.destroyed
http2session.encrypted
http2session.goaway([code[, lastStreamID[, opaqueData]]])
http2session.localSettings
http2session.originSet
http2session.pendingSettingsAck
http2session.ping([payload, ]callback)
http2session.ref()
http2session.remoteSettings
http2session.setTimeout(msecs, callback)
http2session.socket
http2session.state
http2session.settings([settings][, callback])
http2session.type
http2session.unref()
Class: ServerHttp2Session
serverhttp2session.altsvc(alt, originOrStream)
Specifying alternative services
serverhttp2session.origin(...origins)
Class: ClientHttp2Session
Event: 'altsvc'
Event: 'origin'
clienthttp2session.request(headers[, options])
Class: Http2Stream
Http2Stream Lifecycle
Creation
Destruction
Event: 'aborted'
Event: 'close'
Event: 'error'
Event: 'frameError'
Event: 'timeout'
Event: 'trailers'
Event: 'wantTrailers'
http2stream.aborted
http2stream.bufferSize
http2stream.close(code[, callback])
http2stream.closed
http2stream.destroyed
http2stream.endAfterHeaders
http2stream.id
http2stream.pending
http2stream.priority(options)
http2stream.rstCode
http2stream.sentHeaders
http2stream.sentInfoHeaders
http2stream.sentTrailers
http2stream.session
http2stream.setTimeout(msecs, callback)
http2stream.state
http2stream.sendTrailers(headers)
Class: ClientHttp2Stream
Event: 'continue'
Event: 'headers'
Event: 'push'
Event: 'response'
Class: ServerHttp2Stream
http2stream.additionalHeaders(headers)
http2stream.headersSent
http2stream.pushAllowed
http2stream.pushStream(headers[, options], callback)
http2stream.respond([headers[, options]])
http2stream.respondWithFD(fd[, headers[, options]])
http2stream.respondWithFile(path[, headers[, options]])
Class: Http2Server
Event: 'checkContinue'
Event: 'request'
Event: 'session'
Event: 'sessionError'
Event: 'stream'
Event: 'timeout'
server.close([callback])
server.setTimeout([msecs][, callback])
Class: Http2SecureServer
Event: 'checkContinue'
Event: 'request'
Event: 'session'
Event: 'sessionError'
Event: 'stream'
Event: 'timeout'
Event: 'unknownProtocol'
server.close([callback])
server.setTimeout([msecs][, callback])
http2.createServer(options[, onRequestHandler])
http2.createSecureServer(options[, onRequestHandler])
http2.connect(authority[, options][, listener])
http2.constants
Error Codes for RST_STREAM and GOAWAY
http2.getDefaultSettings()
http2.getPackedSettings([settings])
http2.getUnpackedSettings(buf)
Headers Object
Settings Object
Using options.selectPadding()
Error Handling
Invalid character handling in header names and values
Push streams on the client
Supporting the CONNECT method
The Extended CONNECT Protocol
Compatibility API
ALPN negotiation
Class: http2.Http2ServerRequest
Event: 'aborted'
Event: 'close'
request.aborted
request.authority
request.complete
request.destroy([error])
request.headers
request.httpVersion
request.method
request.rawHeaders
request.rawTrailers
request.scheme
request.setTimeout(msecs, callback)
request.socket
request.stream
request.trailers
request.url
Class: http2.Http2ServerResponse
Event: 'close'
Event: 'finish'
response.addTrailers(headers)
response.connection
response.end([data[, encoding]][, callback])
response.finished
response.getHeader(name)
response.getHeaderNames()
response.getHeaders()
response.hasHeader(name)
response.headersSent
response.removeHeader(name)
response.sendDate
response.setHeader(name, value)
response.setTimeout(msecs[, callback])
response.socket
response.statusCode
response.statusMessage
response.stream
response.writableEnded
response.write(chunk[, encoding][, callback])
response.writeContinue()
response.writeHead(statusCode[, statusMessage][, headers])
response.createPushResponse(headers, callback)
Collecting HTTP/2 Performance Metrics
HTTP/2
History
Stability: 2 - Stable
The http2 module provides an implementation of the HTTP/2 protocol. It can be accessed using:
const http2 = require(‘http2’);
Core API
The Core API provides a low-level interface designed specifically around support for HTTP/2 protocol features. It is specifically not designed for compatibility with the existing HTTP/1 module API. However, the Compatibility API is.
The http2 Core API is much more symmetric between client and server than the http API. For instance, most events, like ‘error’, ‘connect’ and ‘stream’, can be emitted either by client-side code or server-side code.
Server-side example
The following illustrates a simple HTTP/2 server using the Core API. Since there are no browsers known that support unencrypted HTTP/2, the use of http2.createSecureServer() is necessary when communicating with browser clients.
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 is a Duplex
stream.respond({
‘content-type’: ‘text/html’,
‘:status’: 200
});
stream.end(‘
Hello World
’);});
server.listen(8443);
To generate the certificate and key for this example, run:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj ‘/CN=localhost’
-keyout localhost-privkey.pem -out localhost-cert.pem
Client-side example
The following illustrates an HTTP/2 client:
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();
Class: Http2Session
Added in: v8.4.0
Extends: <EventEmitter>
Instances of the http2.Http2Session class represent an active communications session between an HTTP/2 client and server. Instances of this class are not intended to be constructed directly by user code.
Each Http2Session instance will exhibit slightly different behaviors depending on whether it is operating as a server or a client. The http2session.type property can be used to determine the mode in which an Http2Session is operating. On the server side, user code should rarely have occasion to work with the Http2Session object directly, with most actions typically taken through interactions with either the Http2Server or Http2Stream objects.
User code will not create Http2Session instances directly. Server-side Http2Session instances are created by the Http2Server instance when a new HTTP/2 connection is received. Client-side Http2Session instances are created using the http2.connect() method.
Http2Session and Sockets
Every Http2Session instance is associated with exactly one net.Socket or tls.TLSSocket when it is created. When either the Socket or the Http2Session are destroyed, both will be destroyed.
Because of the specific serialization and processing requirements imposed by the HTTP/2 protocol, it is not recommended for user code to read data from or write data to a Socket instance bound to a Http2Session. Doing so can put the HTTP/2 session into an indeterminate state causing the session and the socket to become unusable.
Once a Socket has been bound to an Http2Session, user code should rely solely on the API of the Http2Session.
Event: ‘close’
Added in: v8.4.0
The ‘close’ event is emitted once the Http2Session has been destroyed. Its listener does not expect any arguments.
Event: ‘connect’
Added in: v8.4.0
session <Http2Session>
socket <net.Socket>
The ‘connect’ event is emitted once the Http2Session has been successfully connected to the remote peer and communication may begin.
User code will typically not listen for this event directly.
Event: ‘error’
Added in: v8.4.0
error <Error>
The ‘error’ event is emitted when an error occurs during the processing of an Http2Session.
Event: ‘frameError’
Added in: v8.4.0
type <integer> The frame type.
code <integer> The error code.
id <integer> The stream id (or 0 if the frame isn't associated with a stream).
The ‘frameError’ event is emitted when an error occurs while attempting to send a frame on the session. If the frame that could not be sent is associated with a specific Http2Stream, an attempt to emit a ‘frameError’ event on the Http2Stream is made.
If the ‘frameError’ event is associated with a stream, the stream will be closed and destroyed immediately following the ‘frameError’ event. If the event is not associated with a stream, the Http2Session will be shut down immediately following the ‘frameError’ event.
Event: ‘goaway’
Added in: v8.4.0
errorCode <number> The HTTP/2 error code specified in the GOAWAY frame.
lastStreamID <number> The ID of the last stream the remote peer successfully processed (or 0 if no ID is specified).
opaqueData <Buffer> If additional opaque data was included in the GOAWAY frame, a Buffer instance will be passed containing that data.
The ‘goaway’ event is emitted when a GOAWAY frame is received.
The Http2Session instance will be shut down automatically when the ‘goaway’ event is emitted.
Event: ‘localSettings’
Added in: v8.4.0
settings <HTTP/2 Settings Object> A copy of the SETTINGS frame received.
The ‘localSettings’ event is emitted when an acknowledgment SETTINGS frame has been received.
When using http2session.settings() to submit new settings, the modified settings do not take effect until the ‘localSettings’ event is emitted.
session.settings({ enablePush: false });
session.on(‘localSettings’, (settings) => {
/* Use the new settings */
});
Event: ‘ping’
Added in: v10.12.0
payload <Buffer> The PING frame 8-byte payload
The ‘ping’ event is emitted whenever a PING frame is received from the connected peer.
Event: ‘remoteSettings’
Added in: v8.4.0
settings <HTTP/2 Settings Object> A copy of the SETTINGS frame received.
The ‘remoteSettings’ event is emitted when a new SETTINGS frame is received from the connected peer.
session.on(‘remoteSettings’, (settings) => {
/* Use the new settings */
});
Event: ‘stream’
Added in: v8.4.0
stream <Http2Stream> A reference to the stream
headers <HTTP/2 Headers Object> An object describing the headers
flags <number> The associated numeric flags
rawHeaders <Array> An array containing the raw header names followed by their respective values.
The ‘stream’ event is emitted when a new Http2Stream is created.
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’);
});
On the server side, user code will typically not listen for this event directly, and would instead register a handler for the ‘stream’ event emitted by the net.Server or tls.Server instances returned by http2.createServer() and http2.createSecureServer(), respectively, as in the example below:
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(‘
Hello World
’);});
server.listen(80);
Even though HTTP/2 streams and network sockets are not in a 1:1 correspondence, a network error will destroy each individual stream and must be handled on the stream level, as shown above.
Event: ‘timeout’
Added in: v8.4.0
After the http2session.setTimeout() method is used to set the timeout period for this Http2Session, the ‘timeout’ event is emitted if there is no activity on the Http2Session after the configured number of milliseconds. Its listener does not expect any arguments.
session.setTimeout(2000);
session.on(‘timeout’, () => { /* … */ });
http2session.alpnProtocol
Added in: v9.4.0
<string> | <undefined>
Value will be undefined if the Http2Session is not yet connected to a socket, h2c if the Http2Session is not connected to a TLSSocket, or will return the value of the connected TLSSocket’s own alpnProtocol property.
http2session.close([callback])
Added in: v9.4.0
callback <Function>
Gracefully closes the Http2Session, allowing any existing streams to complete on their own and preventing new Http2Stream instances from being created. Once closed, http2session.destroy() might be called if there are no open Http2Stream instances.
If specified, the callback function is registered as a handler for the ‘close’ event.
http2session.closed
Added in: v9.4.0
<boolean>
Will be true if this Http2Session instance has been closed, otherwise false.
http2session.connecting
Added in: v10.0.0
<boolean>
Will be true if this Http2Session instance is still connecting, will be set to false before emitting connect event and/or calling the http2.connect callback.
http2session.destroy([error][, code])
Added in: v8.4.0
error <Error> An Error object if the Http2Session is being destroyed due to an error.
code <number> The HTTP/2 error code to send in the final GOAWAY frame. If unspecified, and error is not undefined, the default is INTERNAL_ERROR, otherwise defaults to NO_ERROR.
Immediately terminates the Http2Session and the associated net.Socket or tls.TLSSocket.
Once destroyed, the Http2Session will emit the ‘close’ event. If error is not undefined, an ‘error’ event will be emitted immediately before the ‘close’ event.
If there are any remaining open Http2Streams associated with the Http2Session, those will also be destroyed.
http2session.destroyed
Added in: v8.4.0
<boolean>
Will be true if this Http2Session instance has been destroyed and must no longer be used, otherwise false.
http2session.encrypted
Added in: v9.4.0
<boolean> | <undefined>
Value is undefined if the Http2Session session socket has not yet been connected, true if the Http2Session is connected with a TLSSocket, and false if the Http2Session is connected to any other kind of socket or stream.
http2session.goaway([code[, lastStreamID[, opaqueData]]])
Added in: v9.4.0
code <number> An HTTP/2 error code
lastStreamID <number> The numeric ID of the last processed Http2Stream
opaqueData <Buffer> | <TypedArray> | <DataView> A TypedArray or DataView instance containing additional data to be carried within the GOAWAY frame.
Transmits a GOAWAY frame to the connected peer without shutting down the Http2Session.
http2session.localSettings
Added in: v8.4.0
<HTTP/2 Settings Object>
A prototype-less object describing the current local settings of this Http2Session. The local settings are local to this Http2Session instance.
http2session.originSet
Added in: v9.4.0
<string[]> | <undefined>
If the Http2Session is connected to a TLSSocket, the originSet property will return an Array of origins for which the Http2Session may be considered authoritative.
The originSet property is only available when using a secure TLS connection.
http2session.pendingSettingsAck
Added in: v8.4.0
<boolean>
Indicates whether the Http2Session is currently waiting for acknowledgment of a sent SETTINGS frame. Will be true after calling the http2session.settings() method. Will be false once all sent SETTINGS frames have been acknowledged.
http2session.ping([payload, ]callback)
Added in: v8.9.3
payload <Buffer> | <TypedArray> | <DataView> Optional ping payload.
callback <Function>
Returns: <boolean>
Sends a PING frame to the connected HTTP/2 peer. A callback function must be provided. The method will return true if the PING was sent, false otherwise.
The maximum number of outstanding (unacknowledged) pings is determined by the maxOutstandingPings configuration option. The default maximum is 10.
If provided, the payload must be a Buffer, TypedArray, or DataView containing 8 bytes of data that will be transmitted with the PING and returned with the ping acknowledgment.
The callback will be invoked with three arguments: an error argument that will be null if the PING was successfully acknowledged, a duration argument that reports the number of milliseconds elapsed since the ping was sent and the acknowledgment was received, and a Buffer containing the 8-byte PING payload.
session.ping(Buffer.from(‘abcdefgh’), (err, duration, payload) => {
if (!err) {
console.log(Ping acknowledged in ${duration} milliseconds