Node.js v25.0.0 文档
- Node.js v25.0.0
-
目录
- HTTP/2
- 确定加密支持是否不可用
- 核心 API
- 服务器端示例
- 客户端示例
- 类:
Http2Session
Http2Session
和套接字- 事件:
'close'
- 事件:
'connect'
- 事件:
'error'
- 事件:
'frameError'
- 事件:
'goaway'
- 事件:
'localSettings'
- 事件:
'ping'
- 事件:
'remoteSettings'
- 事件:
'stream'
- 事件:
'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.setLocalWindowSize(windowSize)
http2session.setTimeout(msecs, callback)
http2session.socket
http2session.state
http2session.settings([settings][, callback])
http2session.type
http2session.unref()
- 类:
ServerHttp2Session
- 类:
ClientHttp2Session
- 类:
Http2Stream
Http2Stream
的生命周期- 事件:
'aborted'
- 事件:
'close'
- 事件:
'error'
- 事件:
'frameError'
- 事件:
'ready'
- 事件:
'timeout'
- 事件:
'trailers'
- 事件:
'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)
- 类:
ClientHttp2Stream
- 类:
ServerHttp2Stream
- 类:
Http2Server
- 类:
Http2SecureServer
http2.createServer([options][, onRequestHandler])
http2.createSecureServer(options[, onRequestHandler])
http2.connect(authority[, options][, listener])
http2.constants
http2.getDefaultSettings()
http2.getPackedSettings([settings])
http2.getUnpackedSettings(buf)
http2.performServerHandshake(socket[, options])
http2.sensitiveHeaders
- Headers 对象
- Settings 对象
- 错误处理
- Header 名称和值中无效字符的处理
- 客户端上的推送流
- 支持
CONNECT
方法 - 扩展的
CONNECT
协议
- 兼容性 API
- ALPN 协商
- 类:
http2.Http2ServerRequest
- 事件:
'aborted'
- 事件:
'close'
request.aborted
request.authority
request.complete
request.connection
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
- 事件:
- 类:
http2.Http2ServerResponse
- 事件:
'close'
- 事件:
'finish'
response.addTrailers(headers)
response.appendHeader(name, value)
response.connection
response.createPushResponse(headers, callback)
response.end([data[, encoding]][, callback])
response.finished
response.getHeader(name)
response.getHeaderNames()
response.getHeaders()
response.hasHeader(name)
response.headersSent
response.removeHeader(name)
response.req
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.writeEarlyHints(hints)
response.writeHead(statusCode[, statusMessage][, headers])
- 事件:
- 收集 HTTP/2 性能指标
- 关于
:authority
和host
的说明
- HTTP/2
-
索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲区
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入器 API
- 子进程
- 集群
- 命令行选项
- 控制台
- 加密
- 调试器
- 已弃用的 API
- 诊断通道
- DNS
- 域
- 环境变量
- 错误
- 事件
- 文件系统
- 全局对象
- HTTP
- HTTP/2
- HTTPS
- 检查器
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:包
- 模块:TypeScript
- 网络
- 操作系统
- 路径
- 性能钩子
- 权限
- 进程
- Punycode
- 查询字符串
- 逐行读取
- REPL
- 报告
- 单一可执行文件应用
- SQLite
- 流
- 字符串解码器
- 测试运行器
- 定时器
- TLS/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用工具
- V8
- 虚拟机
- WASI
- Web Crypto API
- Web Streams API
- 工作线程
- Zlib
- 其他版本
- 选项
HTTP/2#
源代码:lib/http2.js
node:http2
模块提供了 HTTP/2 协议的实现。可以通过以下方式访问:
const http2 = require('node:http2');
确定加密支持是否可用#
Node.js 在构建时可能不包含对 node:crypto
模块的支持。在这种情况下,尝试从 node:http2
中 import
或调用 require('node:http2')
将会导致抛出错误。
使用 CommonJS 时,抛出的错误可以使用 try/catch 捕获。
let http2;
try {
http2 = require('node:http2');
} catch (err) {
console.error('http2 support is disabled!');
}
当使用词法 ESM import
关键字时,只有在尝试加载模块*之前*注册了 process.on('uncaughtException')
的处理程序(例如,使用预加载模块),才能捕获该错误。
使用 ESM 时,如果代码有可能在未启用加密支持的 Node.js 版本上运行,请考虑使用 import()
函数,而不是词法 import
关键字。
let http2;
try {
http2 = await import('node:http2');
} catch (err) {
console.error('http2 support is disabled!');
}
核心 API#
核心 API 提供了一个低级接口,专为支持 HTTP/2 协议特性而设计。它特别强调不与现有的 HTTP/1 模块 API 兼容。然而,兼容性 API 是兼容的。
http2
核心 API 在客户端和服务器之间的对称性比 http
API 强得多。例如,大多数事件,如 'error'
、'connect'
和 'stream'
,既可以由客户端代码触发,也可以由服务器端代码触发。
服务器端示例#
以下示例演示了一个使用核心 API 的简单 HTTP/2 服务器。由于目前没有已知的浏览器支持未加密的 HTTP/2,在与浏览器客户端通信时,必须使用 http2.createSecureServer()
。
import { createSecureServer } from 'node:http2';
import { readFileSync } from 'node:fs';
const server = createSecureServer({
key: readFileSync('localhost-privkey.pem'),
cert: 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; charset=utf-8',
':status': 200,
});
stream.end('<h1>Hello World</h1>');
});
server.listen(8443);
const http2 = require('node:http2');
const fs = require('node: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; charset=utf-8',
':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
客户端示例#
以下示例演示了一个 HTTP/2 客户端:
import { connect } from 'node:http2';
import { readFileSync } from 'node:fs';
const client = connect('https://:8443', {
ca: 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();
const http2 = require('node:http2');
const fs = require('node:fs');
const client = http2.connect('https://: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();
类:Http2Session
#
- 继承自:<EventEmitter>
http2.Http2Session
类的实例表示 HTTP/2 客户端和服务器之间的活动通信会话。用户代码不应该直接构造该类的实例。
每个 Http2Session
实例的行为会根据其作为服务器还是客户端运行而略有不同。http2session.type
属性可用于确定 Http2Session
的运行模式。在服务器端,用户代码很少需要直接操作 Http2Session
对象,大多数操作通常通过与 Http2Server
或 Http2Stream
对象交互来完成。
用户代码不会直接创建 Http2Session
实例。服务器端的 Http2Session
实例由 Http2Server
实例在接收到新的 HTTP/2 连接时创建。客户端的 Http2Session
实例则通过 http2.connect()
方法创建。
Http2Session
和套接字#
每个 Http2Session
实例在创建时都与一个 net.Socket
或 tls.TLSSocket
相关联。当 Socket
或 Http2Session
被销毁时,两者都会被销毁。
由于 HTTP/2 协议有特定的序列化和处理要求,不建议用户代码从绑定到 Http2Session
的 Socket
实例中读取数据或向其写入数据。这样做可能会使 HTTP/2 会话进入不确定状态,导致会话和套接字变得无法使用。
一旦 Socket
被绑定到 Http2Session
,用户代码应完全依赖于 Http2Session
的 API。
事件:'close'
#
'close'
事件在 Http2Session
被销毁后触发。其监听器不接收任何参数。
事件:'connect'
#
session
<Http2Session>socket
<net.Socket>
'connect'
事件在 Http2Session
成功连接到远程对等端并且可以开始通信时触发。
用户代码通常不会直接监听此事件。
事件:'frameError'
#
'frameError'
事件在尝试在会话上发送帧时发生错误时触发。如果无法发送的帧与特定的 Http2Stream
关联,则会尝试在 Http2Stream
上触发一个 'frameError'
事件。
如果 'frameError'
事件与某个流相关联,则该流将在 'frameError'
事件之后立即关闭和销毁。如果事件不与流相关联,则 Http2Session
将在 'frameError'
事件之后立即关闭。
事件:'goaway'
#
errorCode
<number> 在GOAWAY
帧中指定的 HTTP/2 错误码。lastStreamID
<number> 远程对等端成功处理的最后一个流的 ID(如果未指定 ID,则为0
)。opaqueData
<Buffer> 如果GOAWAY
帧中包含了额外的不透明数据,将传递一个包含该数据的Buffer
实例。
'goaway'
事件在接收到 GOAWAY
帧时触发。
当 'goaway'
事件触发时,Http2Session
实例将自动关闭。
事件:'localSettings'
#
settings
<HTTP/2 Settings Object> 收到的SETTINGS
帧的副本。
'localSettings'
事件在收到确认 SETTINGS
帧时触发。
当使用 http2session.settings()
提交新设置时,修改后的设置直到 'localSettings'
事件触发后才会生效。
session.settings({ enablePush: false });
session.on('localSettings', (settings) => {
/* Use the new settings */
});
事件:'remoteSettings'
#
settings
<HTTP/2 Settings Object> 收到的SETTINGS
帧的副本。
'remoteSettings'
事件在从连接的对等端接收到新的 SETTINGS
帧时触发。
session.on('remoteSettings', (settings) => {
/* Use the new settings */
});
事件:'stream'
#
stream
<Http2Stream> 对该流的引用headers
<HTTP/2 Headers Object> 描述 Headers 的对象flags
<number> 相关的数字标志rawHeaders
<HTTP/2 Raw Headers> 包含原始 Headers 的数组
'stream'
事件在创建新的 Http2Stream
时触发。
session.on('stream', (stream, headers, flags) => {
const method = headers[':method'];
const path = headers[':path'];
// ...
stream.respond({
':status': 200,
'content-type': 'text/plain; charset=utf-8',
});
stream.write('hello ');
stream.end('world');
});
在服务器端,用户代码通常不会直接监听此事件,而是会为 http2.createServer()
和 http2.createSecureServer()
返回的 net.Server
或 tls.Server
实例触发的 'stream'
事件注册一个处理器,如下例所示:
import { createServer } from 'node:http2';
// Create an unencrypted HTTP/2 server
const server = createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
stream.on('error', (error) => console.error(error));
stream.end('<h1>Hello World</h1>');
});
server.listen(8000);
const http2 = require('node:http2');
// Create an unencrypted HTTP/2 server
const server = http2.createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
stream.on('error', (error) => console.error(error));
stream.end('<h1>Hello World</h1>');
});
server.listen(8000);
尽管 HTTP/2 流和网络套接字不是一对一对应的关系,但网络错误会销毁每个单独的流,并且必须在流级别上处理,如上所示。
事件:'timeout'
#
在使用 http2session.setTimeout()
方法为此 Http2Session
设置超时期限后,如果 Http2Session
在配置的毫秒数内没有任何活动,则会触发 'timeout'
事件。其监听器不接收任何参数。
session.setTimeout(2000);
session.on('timeout', () => { /* .. */ });
http2session.alpnProtocol
#
- 类型:<string> | <undefined>
如果 Http2Session
尚未连接到套接字,则该值为 undefined
;如果 Http2Session
未连接到 TLSSocket
,则为 h2c
;否则将返回所连接的 TLSSocket
自身的 alpnProtocol
属性值。
http2session.close([callback])
#
callback
<Function>
平滑地关闭 Http2Session
,允许任何现有流自行完成,并阻止创建新的 Http2Stream
实例。一旦关闭,如果没有打开的 Http2Stream
实例,可能会调用 http2session.destroy()
。
如果指定,callback
函数将注册为 'close'
事件的处理程序。
http2session.connecting
#
- 类型:<boolean>
如果此 Http2Session
实例仍在连接中,则为 true
,在触发 connect
事件和/或调用 http2.connect
回调之前将设置为 false
。
http2session.destroy([error][, code])
#
error
<Error> 如果Http2Session
因错误而被销毁,则为一个Error
对象。code
<number> 在最终的GOAWAY
帧中发送的 HTTP/2 错误码。如果未指定,且error
不为 undefined,则默认为INTERNAL_ERROR
,否则默认为NO_ERROR
。
立即终止 Http2Session
及其关联的 net.Socket
或 tls.TLSSocket
。
一旦被销毁,Http2Session
将触发 'close'
事件。如果 error
不为 undefined,则会在 'close'
事件之前立即触发 'error'
事件。
如果与 Http2Session
关联的任何 Http2Streams
仍然打开,它们也将被销毁。
http2session.encrypted
#
- 类型:<boolean> | <undefined>
如果 Http2Session
会话套接字尚未连接,则值为 undefined
;如果 Http2Session
通过 TLSSocket
连接,则为 true
;如果 Http2Session
连接到任何其他类型的套接字或流,则为 false
。
http2session.goaway([code[, lastStreamID[, opaqueData]]])
#
code
<number> 一个 HTTP/2 错误码lastStreamID
<number> 最后处理的Http2Stream
的数字 IDopaqueData
<Buffer> | <TypedArray> | <DataView> 一个包含要在GOAWAY
帧中携带的附加数据的TypedArray
或DataView
实例。
向连接的对等端发送一个 GOAWAY
帧,但不关闭 Http2Session
。
http2session.localSettings
#
一个无原型的对象,描述此 Http2Session
的当前本地设置。本地设置仅限于此 Http2Session
实例。
http2session.originSet
#
- 类型:<string[]> | <undefined>
如果 Http2Session
连接到 TLSSocket
,originSet
属性将返回一个 Array
,其中包含 Http2Session
可能被视为权威的源列表。
originSet
属性仅在使用安全的 TLS 连接时可用。
http2session.pendingSettingsAck
#
- 类型:<boolean>
指示 Http2Session
当前是否正在等待已发送的 SETTINGS
帧的确认。在调用 http2session.settings()
方法后将为 true
。一旦所有已发送的 SETTINGS
帧都得到确认,将变为 false
。
http2session.ping([payload, ]callback)
#
payload
<Buffer> | <TypedArray> | <DataView> 可选的 ping 负载。callback
<Function>- 返回:<boolean>
向连接的 HTTP/2 对等端发送一个 PING
帧。必须提供一个 callback
函数。如果 PING
已发送,该方法返回 true
,否则返回 false
。
未完成(未确认)的 ping 的最大数量由 maxOutstandingPings
配置选项决定。默认最大值为 10。
如果提供,payload
必须是包含 8 字节数据的 Buffer
、TypedArray
或 DataView
,这些数据将与 PING
一起传输,并在 ping 确认时返回。
回调函数将接收三个参数:一个错误参数,如果 PING
成功确认,则为 null
;一个 duration
参数,报告从发送 ping 到接收确认所经过的毫秒数;以及一个包含 8 字节 PING
负载的 Buffer
。
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 位时间戳(小端序)。
http2session.ref()
#
在此 Http2Session
实例的底层 net.Socket
上调用 ref()
。
http2session.remoteSettings
#
一个无原型的对象,描述此 Http2Session
的当前远程设置。远程设置由已连接的 HTTP/2 对等端设置。
http2session.setLocalWindowSize(windowSize)
#
windowSize
<number>
设置本地端点的窗口大小。windowSize
是要设置的总窗口大小,而不是增量。
import { createServer } from 'node:http2';
const server = createServer();
const expectedWindowSize = 2 ** 20;
server.on('session', (session) => {
// Set local window size to be 2 ** 20
session.setLocalWindowSize(expectedWindowSize);
});
const http2 = require('node:http2');
const server = http2.createServer();
const expectedWindowSize = 2 ** 20;
server.on('session', (session) => {
// Set local window size to be 2 ** 20
session.setLocalWindowSize(expectedWindowSize);
});
对于 http2 客户端,合适的事件是 'connect'
或 'remoteSettings'
。
http2session.setTimeout(msecs, callback)
#
msecs
<number>callback
<Function>
用于设置一个回调函数,当 Http2Session
在 msecs
毫秒内没有任何活动时调用。给定的 callback
将作为 'timeout'
事件的监听器注册。
http2session.socket
#
返回一个 Proxy
对象,其行为类似于 net.Socket
(或 tls.TLSSocket
),但将可用方法限制为可安全用于 HTTP/2 的方法。
destroy
、emit
、end
、pause
、read
、resume
和 write
将抛出一个代码为 ERR_HTTP2_NO_SOCKET_MANIPULATION
的错误。更多信息请参见 Http2Session
和套接字。
setTimeout
方法将在此 Http2Session
上调用。
所有其他交互将直接路由到套接字。
http2session.state
#
提供有关 Http2Session
当前状态的杂项信息。
- 类型:<Object>
effectiveLocalWindowSize
<number>Http2Session
当前的本地(接收)流控制窗口大小。effectiveRecvDataLength
<number> 自上一次流控制WINDOW_UPDATE
以来已接收的字节数。nextStreamID
<number> 此Http2Session
下次创建新Http2Stream
时要使用的数字标识符。localWindowSize
<number> 远程对等端在不接收WINDOW_UPDATE
的情况下可以发送的字节数。lastProcStreamID
<number> 最近接收到HEADERS
或DATA
帧的Http2Stream
的数字 ID。remoteWindowSize
<number> 此Http2Session
在不接收WINDOW_UPDATE
的情况下可以发送的字节数。outboundQueueSize
<number> 此Http2Session
的出站队列中当前帧的数量。deflateDynamicTableSize
<number> 出站头压缩状态表的当前大小(以字节为单位)。inflateDynamicTableSize
<number> 入站头压缩状态表的当前大小(以字节为单位)。
一个描述此 Http2Session
当前状态的对象。
http2session.settings([settings][, callback])
#
settings
<HTTP/2 Settings Object>callback
<Function> 一旦会话连接或如果会话已连接,则立即调用的回调函数。err
<Error> | <null>settings
<HTTP/2 Settings Object> 更新后的settings
对象。duration
<integer>
更新此 Http2Session
的当前本地设置,并向连接的 HTTP/2 对等端发送一个新的 SETTINGS
帧。
一旦调用,当会话等待远程对等端确认新设置时,http2session.pendingSettingsAck
属性将为 true
。
新设置将在收到 SETTINGS
确认并触发 'localSettings'
事件后生效。在确认待处理期间可以发送多个 SETTINGS
帧。
http2session.type
#
- 类型:<number>
如果此 Http2Session
实例是服务器,http2session.type
将等于 http2.constants.NGHTTP2_SESSION_SERVER
;如果实例是客户端,则等于 http2.constants.NGHTTP2_SESSION_CLIENT
。
http2session.unref()
#
在此 Http2Session
实例的底层 net.Socket
上调用 unref()
。
类:ServerHttp2Session
#
- 继承自:<Http2Session>
serverhttp2session.altsvc(alt, originOrStream)
#
alt
<string> RFC 7838 中定义的替代服务配置的描述。originOrStream
<number> | <string> | <URL> | <Object> 一个指定源的 URL 字符串(或带有origin
属性的Object
),或一个活动Http2Stream
的数字标识符(由http2stream.id
属性给出)。
向连接的客户端提交一个 ALTSVC
帧(由 RFC 7838 定义)。
import { createServer } from 'node:http2';
const server = 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);
});
const http2 = require('node: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 源。
指定替代服务#
alt
参数的格式由 RFC 7838 严格定义为一个 ASCII 字符串,其中包含与特定主机和端口关联的“替代”协议的逗号分隔列表。
例如,值 'h2="example.org:81"'
表示 HTTP/2 协议在主机 'example.org'
的 TCP/IP 端口 81 上可用。主机和端口必须包含在引号("
)字符内。
可以指定多个替代方案,例如:'h2="example.org:81", h2=":82"'
。
协议标识符(示例中的 'h2'
)可以是任何有效的 ALPN 协议 ID。
Node.js 实现不验证这些值的语法,并按用户提供或从对等端接收的原样传递。
serverhttp2session.origin(...origins)
#
向连接的客户端提交一个 ORIGIN
帧(由 RFC 8336 定义),以宣告服务器能够为其提供权威响应的一组源。
import { createSecureServer } from 'node:http2';
const options = getSecureOptionsSomehow();
const server = createSecureServer(options);
server.on('stream', (stream) => {
stream.respond();
stream.end('ok');
});
server.on('session', (session) => {
session.origin('https://example.com', 'https://example.org');
});
const http2 = require('node:http2');
const options = getSecureOptionsSomehow();
const server = http2.createSecureServer(options);
server.on('stream', (stream) => {
stream.respond();
stream.end('ok');
});
server.on('session', (session) => {
session.origin('https://example.com', 'https://example.org');
});
当字符串作为 origin
传递时,它将被解析为 URL 并派生出源。例如,HTTP URL 'https://example.org/foo/bar'
的源是 ASCII 字符串 'https://example.org'
。如果给定字符串无法解析为 URL 或无法派生有效源,则将抛出错误。
一个 URL
对象或任何带有 origin
属性的对象都可以作为 origin
传递,在这种情况下,将使用 origin
属性的值。origin
属性的值必须是正确序列化的 ASCII 源。
或者,在使用 http2.createSecureServer()
方法创建新的 HTTP/2 服务器时,可以使用 origins
选项:
import { createSecureServer } from 'node:http2';
const options = getSecureOptionsSomehow();
options.origins = ['https://example.com', 'https://example.org'];
const server = createSecureServer(options);
server.on('stream', (stream) => {
stream.respond();
stream.end('ok');
});
const http2 = require('node:http2');
const options = getSecureOptionsSomehow();
options.origins = ['https://example.com', 'https://example.org'];
const server = http2.createSecureServer(options);
server.on('stream', (stream) => {
stream.respond();
stream.end('ok');
});
类:ClientHttp2Session
#
- 继承自:<Http2Session>
事件:'altsvc'
#
'altsvc'
事件在客户端接收到 ALTSVC
帧时触发。该事件将携带 ALTSVC
值、源和流 ID 触发。如果 ALTSVC
帧中未提供 origin
,则 origin
将是一个空字符串。
import { connect } from 'node:http2';
const client = connect('https://example.org');
client.on('altsvc', (alt, origin, streamId) => {
console.log(alt);
console.log(origin);
console.log(streamId);
});
const http2 = require('node:http2');
const client = http2.connect('https://example.org');
client.on('altsvc', (alt, origin, streamId) => {
console.log(alt);
console.log(origin);
console.log(streamId);
});
事件:'origin'
#
origins
<string[]>
'origin'
事件在客户端接收到 ORIGIN
帧时触发。该事件将携带一个 origin
字符串数组触发。http2session.originSet
将被更新以包含接收到的源。
import { connect } from 'node:http2';
const client = connect('https://example.org');
client.on('origin', (origins) => {
for (let n = 0; n < origins.length; n++)
console.log(origins[n]);
});
const http2 = require('node: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 连接时触发。
clienthttp2session.request(headers[, options])
#
-
headers
<HTTP/2 Headers Object> | <HTTP/2 Raw Headers> -
options
<Object>endStream
<boolean> 如果Http2Stream
的可写端应初始关闭,则为true
,例如在发送不应期望有负载体的GET
请求时。exclusive
<boolean> 当为true
且parent
标识了一个父流时,创建的流将成为父流的唯一直接依赖项,所有其他现有依赖项都将成为新创建流的依赖项。默认值:false
。parent
<number> 指定新创建流所依赖的流的数字标识符。waitForTrailers
<boolean> 当为true
时,Http2Stream
将在发送最后一个DATA
帧后触发'wantTrailers'
事件。signal
<AbortSignal> 一个可用于中止正在进行的请求的 AbortSignal。
仅对于 HTTP/2 客户端 Http2Session
实例,http2session.request()
方法会创建并返回一个 Http2Stream
实例,可用于向连接的服务器发送 HTTP/2 请求。
当 ClientHttp2Session
首次创建时,套接字可能尚未连接。如果在此期间调用 clienthttp2session.request()
,实际的请求将被延迟,直到套接字准备就绪。如果在实际请求执行前关闭了 session
,则会抛出 ERR_HTTP2_GOAWAY_SESSION
错误。
此方法仅在 http2session.type
等于 http2.constants.NGHTTP2_SESSION_CLIENT
时可用。
import { connect, constants } from 'node:http2';
const clientSession = connect('https://:1234');
const {
HTTP2_HEADER_PATH,
HTTP2_HEADER_STATUS,
} = 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', () => { /* .. */ });
});
const http2 = require('node:http2');
const clientSession = http2.connect('https://: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()
方法向对等端发送尾部 Headers。
当设置了 options.waitForTrailers
时,Http2Stream
不会在传输最后一个 DATA
帧后自动关闭。用户代码必须调用 http2stream.sendTrailers()
或 http2stream.close()
来关闭 Http2Stream
。
当使用 AbortSignal
设置 options.signal
,然后调用相应 AbortController
上的 abort
时,请求将触发一个带有 AbortError
错误的 'error'
事件。
:method
和 :path
伪头未在 headers
中指定,它们分别默认为:
:method
='GET'
:path
=/
类:Http2Stream
#
- 继承自:<stream.Duplex>
Http2Stream
类的每个实例代表一个通过 Http2Session
实例的双向 HTTP/2 通信流。任何单个 Http2Session
在其生命周期内最多可以有 231-1 个 Http2Stream
实例。
用户代码不会直接构造 Http2Stream
实例。相反,这些实例由 Http2Session
实例创建、管理并提供给用户代码。在服务器上,Http2Stream
实例要么响应传入的 HTTP 请求而创建(并通过 'stream'
事件交给用户代码),要么响应对 http2stream.pushStream()
方法的调用而创建。在客户端,Http2Stream
实例在调用 http2session.request()
方法时创建并返回,或响应传入的 'push'
事件而创建。
Http2Stream
类是 ServerHttp2Stream
和 ClientHttp2Stream
类的基类,它们分别专用于服务器端和客户端。
所有 Http2Stream
实例都是 Duplex
流。Duplex
的 Writable
端用于向连接的对等端发送数据,而 Readable
端用于接收连接的对等端发送的数据。
Http2Stream
的默认文本字符编码是 UTF-8。当使用 Http2Stream
发送文本时,请使用 'content-type'
头来设置字符编码。
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
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
属性将指定 RST_STREAM
错误码。一旦被销毁,Http2Stream
实例将不再可用。
事件:'aborted'
#
'aborted'
事件在 Http2Stream
实例在通信中途被异常中止时触发。其监听器不接收任何参数。
'aborted'
事件仅在 Http2Stream
可写端尚未结束时触发。
事件:'close'
#
'close'
事件在 Http2Stream
被销毁时触发。一旦此事件触发,Http2Stream
实例将不再可用。
关闭流时使用的 HTTP/2 错误码可以通过 http2stream.rstCode
属性获取。如果代码是除 NGHTTP2_NO_ERROR
(0
) 之外的任何值,则也已触发了 'error'
事件。
事件:'frameError'
#
'frameError'
事件在尝试发送帧时发生错误时触发。调用时,处理函数将接收一个标识帧类型的整数参数和一个标识错误码的整数参数。Http2Stream
实例将在 'frameError'
事件触发后立即销毁。
事件:'ready'
#
'ready'
事件在 Http2Stream
已打开、已分配 id
并可使用时触发。监听器不接收任何参数。
事件:'timeout'
#
在使用 http2stream.setTimeout()
设置的毫秒数内,如果此 Http2Stream
未收到任何活动,则会触发 'timeout'
事件。其监听器不接收任何参数。
事件:'trailers'
#
headers
<HTTP/2 Headers Object> 描述 Headers 的对象flags
<number> 相关的数字标志
'trailers'
事件在接收到与尾部头字段关联的头块时触发。监听器回调函数将接收到 HTTP/2 Headers 对象和与头关联的标志。
如果在接收到尾部数据之前调用了 http2stream.end()
,并且没有读取或监听传入的数据,则可能不会触发此事件。
stream.on('trailers', (headers, flags) => {
console.log(headers);
});
事件:'wantTrailers'
#
当 Http2Stream
已将最后一个 DATA
帧排队发送,并且 Http2Stream
准备好发送尾部头时,会触发 'wantTrailers'
事件。在发起请求或响应时,必须设置 waitForTrailers
选项才能触发此事件。
http2stream.close(code[, callback])
#
code
<number> 标识错误码的无符号 32 位整数。默认值:http2.constants.NGHTTP2_NO_ERROR
(0x00
)。callback
<Function> 一个可选的函数,注册用于监听'close'
事件。
通过向连接的 HTTP/2 对等端发送一个 RST_STREAM
帧来关闭 Http2Stream
实例。
http2stream.endAfterHeaders
#
- 类型:<boolean>
如果接收到的请求或响应 HEADERS 帧中设置了 END_STREAM
标志,则设置为 true
,表示不应再接收额外数据,并且 Http2Stream
的可读端将被关闭。
http2stream.rstCode
#
- 类型:<number>
当 Http2Stream
在接收到来自连接对等端的 RST_STREAM
帧、调用 http2stream.close()
或 http2stream.destroy()
后被销毁时,设置为报告的 RST_STREAM
错误码。如果 Http2Stream
尚未关闭,则为 undefined
。
http2stream.session
#
对此 Http2Stream
所属的 Http2Session
实例的引用。在 Http2Stream
实例被销毁后,该值将为 undefined
。
http2stream.setTimeout(msecs, callback)
#
msecs
<number>callback
<Function>
import { connect, constants } from 'node:http2';
const client = connect('http://example.org:8000');
const { NGHTTP2_CANCEL } = constants;
const req = client.request({ ':path': '/' });
// Cancel the stream if there's no activity after 5 seconds
req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));
const http2 = require('node: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));
http2stream.state
#
提供有关 Http2Stream
当前状态的杂项信息。
- 类型:<Object>
localWindowSize
<number> 连接的对等端可以为此Http2Stream
发送的字节数,而无需接收WINDOW_UPDATE
。state
<number> 一个标志,指示由nghttp2
确定的Http2Stream
的底层当前状态。localClose
<number> 如果此Http2Stream
已在本地关闭,则为1
。remoteClose
<number> 如果此Http2Stream
已在远程关闭,则为1
。sumDependencyWeight
<number> 旧版属性,始终设置为0
。weight
<number> 旧版属性,始终设置为16
。
此 Http2Stream
的当前状态。
http2stream.sendTrailers(headers)
#
headers
<HTTP/2 Headers Object>
向连接的 HTTP/2 对等端发送一个尾部 HEADERS
帧。此方法将导致 Http2Stream
立即关闭,并且只能在 'wantTrailers'
事件触发后调用。当发送请求或发送响应时,必须设置 options.waitForTrailers
选项,以便在最后一个 DATA
帧之后保持 Http2Stream
打开,从而可以发送尾部数据。
import { createServer } from 'node:http2';
const server = createServer();
server.on('stream', (stream) => {
stream.respond(undefined, { waitForTrailers: true });
stream.on('wantTrailers', () => {
stream.sendTrailers({ xyz: 'abc' });
});
stream.end('Hello World');
});
const http2 = require('node: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'
等)。
类:ClientHttp2Stream
#
- 继承自 <Http2Stream>
ClientHttp2Stream
类是 Http2Stream
的扩展,专门用于 HTTP/2 客户端。客户端上的 Http2Stream
实例提供诸如 'response'
和 'push'
等仅与客户端相关的事件。
事件:'continue'
#
当服务器发送 100 Continue
状态时触发,通常是因为请求包含了 Expect: 100-continue
。这是一个指示客户端应该发送请求体的指令。
事件:'headers'
#
headers
<HTTP/2 Headers Object>flags
<number>rawHeaders
<HTTP/2 Raw Headers>
'headers'
事件在接收到流的附加头块时触发,例如当接收到 1xx
信息头块时。监听器回调函数会接收到 HTTP/2 Headers 对象、与头关联的标志以及原始格式的头(参见 HTTP/2 原始 Headers)。
stream.on('headers', (headers, flags) => {
console.log(headers);
});
事件:'push'
#
headers
<HTTP/2 Headers Object>flags
<number>
'push'
事件在接收到服务器推送流的响应头时触发。监听器回调函数会接收到 HTTP/2 Headers 对象和与头关联的标志。
stream.on('push', (headers, flags) => {
console.log(headers);
});
事件:'response'
#
headers
<HTTP/2 Headers Object>flags
<number>rawHeaders
<HTTP/2 Raw Headers>
'response'
事件在此流从连接的 HTTP/2 服务器接收到响应 HEADERS
帧时触发。监听器将接收三个参数:一个包含接收到的 HTTP/2 Headers 对象的 Object
,与头关联的标志,以及原始格式的头(参见 HTTP/2 原始 Headers)。
import { connect } from 'node:http2';
const client = connect('https://');
const req = client.request({ ':path': '/' });
req.on('response', (headers, flags) => {
console.log(headers[':status']);
});
const http2 = require('node:http2');
const client = http2.connect('https://');
const req = client.request({ ':path': '/' });
req.on('response', (headers, flags) => {
console.log(headers[':status']);
});
类:ServerHttp2Stream
#
- 继承自:<Http2Stream>
ServerHttp2Stream
类是 Http2Stream
的扩展,专门用于 HTTP/2 服务器。服务器上的 Http2Stream
实例提供了诸如 http2stream.pushStream()
和 http2stream.respond()
等仅与服务器相关的方法。
http2stream.additionalHeaders(headers)
#
headers
<HTTP/2 Headers Object>
向连接的 HTTP/2 对等端发送一个附加的信息性 HEADERS
帧。
http2stream.pushAllowed
#
- 类型:<boolean>
只读属性,映射到远程客户端最新 SETTINGS
帧的 SETTINGS_ENABLE_PUSH
标志。如果远程对等端接受推送流,则为 true
,否则为 false
。在同一个 Http2Session
中的每个 Http2Stream
的设置都是相同的。
http2stream.pushStream(headers[, options], callback)
#
headers
<HTTP/2 Headers Object>options
<Object>callback
<Function> 推送流启动后调用的回调函数。err
<Error>pushStream
<ServerHttp2Stream> 返回的pushStream
对象。headers
<HTTP/2 Headers Object>pushStream
启动时使用的头对象。
启动一个推送流。回调函数被调用时,会将为推送流创建的新的 Http2Stream
实例作为第二个参数传递,或者将一个 Error
作为第一个参数传递。
import { createServer } from 'node:http2';
const server = 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');
});
const http2 = require('node: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()
,否则会抛出错误。
http2stream.respond([headers[, options]])
#
headers
<HTTP/2 Headers Object> | <HTTP/2 Raw Headers>options
<Object>
import { createServer } from 'node:http2';
const server = createServer();
server.on('stream', (stream) => {
stream.respond({ ':status': 200 });
stream.end('some data');
});
const http2 = require('node: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
。
import { createServer } from 'node:http2';
const server = 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');
});
const http2 = require('node: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');
});
http2stream.respondWithFD(fd[, headers[, options]])
#
fd
<number> | <FileHandle> 一个可读的文件描述符。headers
<HTTP/2 Headers Object>options
<Object>statCheck
<Function>waitForTrailers
<boolean> 当为true
时,Http2Stream
将在发送最后一个DATA
帧后触发'wantTrailers'
事件。offset
<number> 开始读取的偏移位置。length
<number> 从 fd 发送的数据量。
启动一个响应,其数据从给定的文件描述符中读取。不对给定的文件描述符进行验证。如果在尝试使用文件描述符读取数据时发生错误,Http2Stream
将使用标准的 INTERNAL_ERROR
代码通过 RST_STREAM
帧关闭。
使用此方法时,Http2Stream
对象的 Duplex
接口将自动关闭。
import { createServer } from 'node:http2';
import { openSync, fstatSync, closeSync } from 'node:fs';
const server = createServer();
server.on('stream', (stream) => {
const fd = openSync('/some/file', 'r');
const stat = fstatSync(fd);
const headers = {
'content-length': stat.size,
'last-modified': stat.mtime.toUTCString(),
'content-type': 'text/plain; charset=utf-8',
};
stream.respondWithFD(fd, headers);
stream.on('close', () => closeSync(fd));
});
const http2 = require('node:http2');
const fs = require('node: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; charset=utf-8',
};
stream.respondWithFD(fd, headers);
stream.on('close', () => fs.closeSync(fd));
});
可以指定可选的 options.statCheck
函数,让用户代码有机会根据给定 fd 的 fs.Stat
详细信息设置额外的内容头。如果提供了 statCheck
函数,http2stream.respondWithFD()
方法将执行 fs.fstat()
调用以收集有关所提供文件描述符的详细信息。
offset
和 length
选项可用于将响应限制为特定的范围子集。例如,这可以用于支持 HTTP Range 请求。
流关闭时,文件描述符或 FileHandle
不会关闭,因此在不再需要时需要手动关闭。不支持并发地为多个流使用相同的文件描述符,这可能导致数据丢失。在一个流完成后重用文件描述符是支持的。
当设置了 options.waitForTrailers
选项时,'wantTrailers'
事件将在将最后一个负载数据块排队发送后立即触发。然后可以使用 http2stream.sendTrailers()
方法向对等端发送尾部头字段。
当设置了 options.waitForTrailers
时,Http2Stream
在传输最后一个 DATA
帧时不会自动关闭。用户代码必须调用 http2stream.sendTrailers()
或 http2stream.close()
来关闭 Http2Stream
。
import { createServer } from 'node:http2';
import { openSync, fstatSync, closeSync } from 'node:fs';
const server = createServer();
server.on('stream', (stream) => {
const fd = openSync('/some/file', 'r');
const stat = fstatSync(fd);
const headers = {
'content-length': stat.size,
'last-modified': stat.mtime.toUTCString(),
'content-type': 'text/plain; charset=utf-8',
};
stream.respondWithFD(fd, headers, { waitForTrailers: true });
stream.on('wantTrailers', () => {
stream.sendTrailers({ ABC: 'some value to send' });
});
stream.on('close', () => closeSync(fd));
});
const http2 = require('node:http2');
const fs = require('node: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; charset=utf-8',
};
stream.respondWithFD(fd, headers, { waitForTrailers: true });
stream.on('wantTrailers', () => {
stream.sendTrailers({ ABC: 'some value to send' });
});
stream.on('close', () => fs.closeSync(fd));
});
http2stream.respondWithFile(path[, headers[, options]])
#
path
<string> | <Buffer> | <URL>headers
<HTTP/2 Headers Object>options
<Object>statCheck
<Function>onError
<Function> 在发送前发生错误时调用的回调函数。waitForTrailers
<boolean> 当为true
时,Http2Stream
将在发送最后一个DATA
帧后触发'wantTrailers'
事件。offset
<number> 开始读取的偏移位置。length
<number> 从 fd 发送的数据量。
将一个常规文件作为响应发送。path
必须指定一个常规文件,否则将在 Http2Stream
对象上触发 'error'
事件。
使用此方法时,Http2Stream
对象的 Duplex
接口将自动关闭。
可以指定可选的 options.statCheck
函数,让用户代码有机会根据给定文件的 fs.Stat
详细信息设置额外的内容头。
如果在尝试读取文件数据时发生错误,Http2Stream
将使用标准的 INTERNAL_ERROR
代码通过 RST_STREAM
帧关闭。如果定义了 onError
回调,则会调用它。否则流将被销毁。
使用文件路径的示例:
import { createServer } from 'node:http2';
const server = createServer();
server.on('stream', (stream) => {
function statCheck(stat, headers) {
headers['last-modified'] = stat.mtime.toUTCString();
}
function onError(err) {
// stream.respond() can throw if the stream has been destroyed by
// the other side.
try {
if (err.code === 'ENOENT') {
stream.respond({ ':status': 404 });
} else {
stream.respond({ ':status': 500 });
}
} catch (err) {
// Perform actual error handling.
console.error(err);
}
stream.end();
}
stream.respondWithFile('/some/file',
{ 'content-type': 'text/plain; charset=utf-8' },
{ statCheck, onError });
});
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
function statCheck(stat, headers) {
headers['last-modified'] = stat.mtime.toUTCString();
}
function onError(err) {
// stream.respond() can throw if the stream has been destroyed by
// the other side.
try {
if (err.code === 'ENOENT') {
stream.respond({ ':status': 404 });
} else {
stream.respond({ ':status': 500 });
}
} catch (err) {
// Perform actual error handling.
console.error(err);
}
stream.end();
}
stream.respondWithFile('/some/file',
{ 'content-type': 'text/plain; charset=utf-8' },
{ statCheck, onError });
});
options.statCheck
函数也可以通过返回 false
来取消发送操作。例如,一个条件请求可以检查 stat 结果来确定文件是否已被修改,以返回一个适当的 304
响应。
import { createServer } from 'node:http2';
const server = 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; charset=utf-8' },
{ statCheck });
});
const http2 = require('node: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; charset=utf-8' },
{ statCheck });
});
content-length
头字段将被自动设置。
offset
和 length
选项可用于将响应限制为特定的范围子集。例如,这可以用于支持 HTTP Range 请求。
options.onError
函数也可以用来处理在文件交付开始前可能发生的所有错误。默认行为是销毁流。
当设置了 options.waitForTrailers
选项时,'wantTrailers'
事件将在将最后一个负载数据块排队发送后立即触发。然后可以使用 http2stream.sendTrailers()
方法向对等端发送尾部头字段。
当设置了 options.waitForTrailers
时,Http2Stream
不会在传输最后一个 DATA
帧后自动关闭。用户代码必须调用 http2stream.sendTrailers()
或 http2stream.close()
来关闭 Http2Stream
。
import { createServer } from 'node:http2';
const server = createServer();
server.on('stream', (stream) => {
stream.respondWithFile('/some/file',
{ 'content-type': 'text/plain; charset=utf-8' },
{ waitForTrailers: true });
stream.on('wantTrailers', () => {
stream.sendTrailers({ ABC: 'some value to send' });
});
});
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
stream.respondWithFile('/some/file',
{ 'content-type': 'text/plain; charset=utf-8' },
{ waitForTrailers: true });
stream.on('wantTrailers', () => {
stream.sendTrailers({ ABC: 'some value to send' });
});
});
类:Http2Server
#
- 继承自:<net.Server>
Http2Server
的实例是使用 http2.createServer()
函数创建的。Http2Server
类不由 node:http2
模块直接导出。
事件:'checkContinue'
#
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
如果注册了 'request'
监听器或 http2.createServer()
提供了一个回调函数,那么每次收到带有 HTTP Expect: 100-continue
的请求时,都会触发 'checkContinue'
事件。如果没有监听此事件,服务器将自动响应一个 100 Continue
状态(如果适用)。
处理此事件需要调用 response.writeContinue()
(如果客户端应继续发送请求体),或生成一个适当的 HTTP 响应(例如 400 Bad Request)(如果客户端不应继续发送请求体)。
当此事件被触发并处理时,'request'
事件将不会被触发。
事件:'connection'
#
socket
<stream.Duplex>
当建立新的 TCP 流时会触发此事件。socket
通常是 net.Socket
类型的对象。用户通常不需要访问此事件。
用户也可以显式地触发此事件,以将连接注入到 HTTP 服务器中。在这种情况下,可以传递任何 Duplex
流。
事件:'request'
#
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
每次有请求时都会触发。每个会话可能会有多个请求。请参阅兼容性 API。
事件:'sessionError'
#
error
<Error>session
<ServerHttp2Session>
当与 Http2Server
关联的 Http2Session
对象触发 'error'
事件时,会触发 'sessionError'
事件。
事件:'stream'
#
stream
<Http2Stream> 对该流的引用headers
<HTTP/2 Headers Object> 描述 Headers 的对象flags
<number> 相关的数字标志rawHeaders
<HTTP/2 Raw Headers> 包含原始 Headers 的数组
当与服务器关联的 Http2Session
触发了 'stream'
事件时,会触发 'stream'
事件。
另请参阅 Http2Session
的 'stream'
事件。
import { createServer, constants } from 'node:http2';
const {
HTTP2_HEADER_METHOD,
HTTP2_HEADER_PATH,
HTTP2_HEADER_STATUS,
HTTP2_HEADER_CONTENT_TYPE,
} = constants;
const server = 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; charset=utf-8',
});
stream.write('hello ');
stream.end('world');
});
const http2 = require('node: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; charset=utf-8',
});
stream.write('hello ');
stream.end('world');
});
事件:'timeout'
#
当服务器在通过 http2server.setTimeout()
设置的给定毫秒数内没有任何活动时,会触发 'timeout'
事件。默认值:0(无超时)。
server.close([callback])
#
callback
<Function>
阻止服务器建立新的会话。由于 HTTP/2 会话的持久性,这不会阻止创建新的请求流。要优雅地关闭服务器,请在所有活动会话上调用 http2session.close()
。
如果提供了 callback
,它将在所有活动会话关闭后才被调用,尽管服务器已经停止接受新会话。更多详情请参阅 net.Server.close()
。
server[Symbol.asyncDispose]()
#
调用 server.close()
并返回一个 Promise,该 Promise 在服务器关闭时兑现。
server.setTimeout([msecs][, callback])
#
msecs
<number> 默认值:0(无超时)callback
<Function>- 返回:<Http2Server>
用于设置 http2 服务器请求的超时值,并设置一个回调函数,当 Http2Server
在 msecs
毫秒后没有任何活动时调用该函数。
给定的回调函数会作为监听器注册到 'timeout'
事件上。
如果 callback
不是一个函数,将会抛出一个新的 ERR_INVALID_ARG_TYPE
错误。
server.timeout
#
- 类型:<number> 超时时间(毫秒)。默认值:0(无超时)
套接字被假定为超时前的不活动毫秒数。
值 0
将禁用传入连接的超时行为。
套接字超时逻辑在连接时设置,因此更改此值仅影响到服务器的新连接,不影响任何现有连接。
server.updateSettings([settings])
#
settings
<HTTP/2 Settings Object>
用于使用提供的设置更新服务器。
对于无效的 settings
值,会抛出 ERR_HTTP2_INVALID_SETTING_VALUE
。
对于无效的 settings
参数,会抛出 ERR_INVALID_ARG_TYPE
。
类:Http2SecureServer
#
- 继承自:<tls.Server>
Http2SecureServer
的实例是使用 http2.createSecureServer()
函数创建的。Http2SecureServer
类不由 node:http2
模块直接导出。
事件:'checkContinue'
#
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
如果注册了 'request'
监听器,或者 http2.createSecureServer()
提供了一个回调函数,那么每当收到带有 HTTP Expect: 100-continue
的请求时,就会触发 'checkContinue'
事件。如果没有监听此事件,服务器将自动酌情响应状态码 100 Continue
。
处理此事件需要调用 response.writeContinue()
(如果客户端应继续发送请求体),或生成一个适当的 HTTP 响应(例如 400 Bad Request)(如果客户端不应继续发送请求体)。
当此事件被触发并处理时,'request'
事件将不会被触发。
事件:'connection'
#
socket
<stream.Duplex>
在 TLS 握手开始之前,当建立新的 TCP 流时,会触发此事件。socket
通常是 net.Socket
类型的对象。用户通常不需要访问此事件。
用户也可以显式地触发此事件,以将连接注入到 HTTP 服务器中。在这种情况下,可以传递任何 Duplex
流。
事件:'request'
#
request
<http2.Http2ServerRequest>response
<http2.Http2ServerResponse>
每次有请求时都会触发。每个会话可能会有多个请求。请参阅兼容性 API。
事件:'session'
#
session
<ServerHttp2Session>
当 Http2SecureServer
创建新的 Http2Session
时,会触发 'session'
事件。
事件:'sessionError'
#
error
<Error>session
<ServerHttp2Session>
当与 Http2SecureServer
关联的 Http2Session
对象触发 'error'
事件时,会触发 'sessionError'
事件。
事件:'stream'
#
stream
<Http2Stream> 对该流的引用headers
<HTTP/2 Headers Object> 描述 Headers 的对象flags
<number> 相关的数字标志rawHeaders
<HTTP/2 Raw Headers> 包含原始 Headers 的数组
当与服务器关联的 Http2Session
触发了 'stream'
事件时,会触发 'stream'
事件。
另请参阅 Http2Session
的 'stream'
事件。
import { createSecureServer, constants } from 'node:http2';
const {
HTTP2_HEADER_METHOD,
HTTP2_HEADER_PATH,
HTTP2_HEADER_STATUS,
HTTP2_HEADER_CONTENT_TYPE,
} = constants;
const options = getOptionsSomehow();
const server = 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; charset=utf-8',
});
stream.write('hello ');
stream.end('world');
});
const http2 = require('node: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; charset=utf-8',
});
stream.write('hello ');
stream.end('world');
});
事件:'timeout'
#
当服务器在通过 http2secureServer.setTimeout()
设置的给定毫秒数内没有任何活动时,会触发 'timeout'
事件。默认值:2 分钟。
事件:'unknownProtocol'
#
socket
<stream.Duplex>
当连接的客户端未能协商一个允许的协议(即 HTTP/2 或 HTTP/1.1)时,会触发 'unknownProtocol'
事件。事件处理程序会接收到用于处理的套接字。如果没有为此事件注册监听器,连接将被终止。可以使用传递给 http2.createSecureServer()
的 'unknownProtocolTimeout'
选项指定超时时间。
在早期版本的 Node.js 中,如果 allowHTTP1
为 false
,并且在 TLS 握手期间,客户端既没有发送 ALPN 扩展,也没有发送不包含 HTTP/2 (h2
) 的 ALPN 扩展,则会触发此事件。较新版本的 Node.js 仅在 allowHTTP1
为 false
且客户端未发送 ALPN 扩展时才触发此事件。如果客户端发送的 ALPN 扩展不包含 HTTP/2(或在 allowHTTP1
为 true
时不包含 HTTP/1.1),TLS 握手将失败,并且不会建立安全连接。
请参阅兼容性 API。
server.close([callback])
#
callback
<Function>
阻止服务器建立新的会话。由于 HTTP/2 会话的持久性,这不会阻止创建新的请求流。要优雅地关闭服务器,请在所有活动会话上调用 http2session.close()
。
如果提供了 callback
,它将在所有活动会话关闭后才被调用,尽管服务器已经停止接受新会话。更多详情请参阅 tls.Server.close()
。
server.setTimeout([msecs][, callback])
#
msecs
<number> 默认值:120000
(2 分钟)callback
<Function>- 返回:<Http2SecureServer>
用于设置 http2 安全服务器请求的超时值,并设置一个回调函数,当 Http2SecureServer
在 msecs
毫秒后没有任何活动时调用该函数。
给定的回调函数会作为监听器注册到 'timeout'
事件上。
如果 callback
不是一个函数,将会抛出一个新的 ERR_INVALID_ARG_TYPE
错误。
server.timeout
#
- 类型:<number> 超时时间(毫秒)。默认值:0(无超时)
套接字被假定为超时前的不活动毫秒数。
值 0
将禁用传入连接的超时行为。
套接字超时逻辑在连接时设置,因此更改此值仅影响到服务器的新连接,不影响任何现有连接。
server.updateSettings([settings])
#
settings
<HTTP/2 Settings Object>
用于使用提供的设置更新服务器。
对于无效的 settings
值,会抛出 ERR_HTTP2_INVALID_SETTING_VALUE
。
对于无效的 settings
参数,会抛出 ERR_INVALID_ARG_TYPE
。
http2.createServer([options][, onRequestHandler])
#
options
<Object>maxDeflateDynamicTableSize
<number> 设置用于压缩标头字段的最大动态表大小。默认值:4Kib
。maxSettings
<number> 设置每个SETTINGS
帧的最大设置条目数。允许的最小值为1
。默认值:32
。maxSessionMemory
<number> 设置Http2Session
允许使用的最大内存。该值以兆字节为单位表示,例如1
等于 1 兆字节。允许的最小值为1
。这是一个基于信用的限制,现有的Http2Stream
可能会导致超过此限制,但当超过此限制时,新的Http2Stream
实例将被拒绝。当前Http2Stream
会话的数量、标头压缩表的当前内存使用量、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。默认值:10
。maxHeaderListPairs
<number> 设置标头条目的最大数量。这类似于node:http
模块中的server.maxHeadersCount
或request.maxHeadersCount
。最小值为4
。默认值:128
。maxOutstandingPings
<number> 设置未完成、未确认的 ping 的最大数量。默认值:10
。maxSendHeaderBlockLength
<number> 设置序列化、压缩的标头块的最大允许大小。尝试发送超过此限制的标头将导致触发'frameError'
事件,并且流将被关闭和销毁。虽然这为整个标头块设置了最大允许大小,但nghttp2
(内部 http2 库)对每个解压缩的键/值对有65536
的限制。paddingStrategy
<number> 用于确定HEADERS
和DATA
帧使用的填充量的策略。默认值:http2.constants.PADDING_STRATEGY_NONE
。值可以是以下之一http2.constants.PADDING_STRATEGY_NONE
:不应用填充。http2.constants.PADDING_STRATEGY_MAX
:应用由内部实现确定的最大填充量。http2.constants.PADDING_STRATEGY_ALIGNED
:尝试应用足够的填充以确保包括 9 字节标头在内的总帧长是 8 的倍数。对于每个帧,都有一个由当前流控制状态和设置确定的最大允许填充字节数。如果此最大值小于确保对齐所需的计算量,则使用最大值,并且总帧长不一定按 8 字节对齐。
peerMaxConcurrentStreams
<number> 设置远程对端的最大并发流数量,就像收到了一个SETTINGS
帧一样。如果远程对端设置了自己的maxConcurrentStreams
值,则此值将被覆盖。默认值:100
。maxSessionInvalidFrames
<integer> 设置在会话关闭前将容忍的最大无效帧数。默认值:1000
。maxSessionRejectedStreams
<integer> 设置在会话关闭前将容忍的在创建时被拒绝的最大流数。每次拒绝都与一个NGHTTP2_ENHANCE_YOUR_CALM
错误相关联,该错误应告知对端不要再打开更多流,因此继续打开流被视为行为不端的对端的标志。默认值:100
。settings
<HTTP/2 Settings Object> 连接时发送给远程对端的初始设置。streamResetBurst
<number> 和streamResetRate
<number> 设置传入流重置(RST_STREAM 帧)的速率限制。必须同时设置这两个设置才能生效,默认值分别为 1000 和 33。remoteCustomSettings
<Array> 整数值数组,用于确定设置类型,这些类型包含在接收到的 remoteSettings 的CustomSettings
属性中。有关允许的设置类型的更多信息,请参阅Http2Settings
对象的CustomSettings
属性。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
。unknownProtocolTimeout
<number> 指定当触发'unknownProtocol'
事件时服务器应等待的超时时间(毫秒)。如果到那时套接字尚未被销毁,服务器将销毁它。默认值:10000
。strictFieldWhitespaceValidation
<boolean> 如果为true
,则根据 RFC-9113 对 HTTP/2 标头字段名称和值进行严格的前导和尾随空格验证。默认值:true
。...options
<Object> 可以提供任何net.createServer()
选项。
onRequestHandler
<Function> 请参阅兼容性 API- 返回:<Http2Server>
返回一个创建和管理 Http2Session
实例的 net.Server
实例。
由于没有已知的浏览器支持未加密的 HTTP/2,因此在与浏览器客户端通信时必须使用 http2.createSecureServer()
。
import { createServer } from 'node:http2';
// Create an unencrypted HTTP/2 server.
// Since there are no browsers known that support
// unencrypted HTTP/2, the use of `createSecureServer()`
// is necessary when communicating with browser clients.
const server = createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
stream.end('<h1>Hello World</h1>');
});
server.listen(8000);
const http2 = require('node:http2');
// Create an unencrypted HTTP/2 server.
// Since there are no browsers known that support
// unencrypted HTTP/2, the use of `http2.createSecureServer()`
// is necessary when communicating with browser clients.
const server = http2.createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
stream.end('<h1>Hello World</h1>');
});
server.listen(8000);
http2.createSecureServer(options[, onRequestHandler])
#
options
<Object>allowHTTP1
<boolean> 当设置为true
时,不支持 HTTP/2 的传入客户端连接将被降级到 HTTP/1.x。请参阅'unknownProtocol'
事件。请参阅 ALPN 协商。默认值:false
。maxDeflateDynamicTableSize
<number> 设置用于压缩标头字段的最大动态表大小。默认值:4Kib
。maxSettings
<number> 设置每个SETTINGS
帧的最大设置条目数。允许的最小值为1
。默认值:32
。maxSessionMemory
<number> 设置Http2Session
允许使用的最大内存。该值以兆字节为单位表示,例如1
等于 1 兆字节。允许的最小值为1
。这是一个基于信用的限制,现有的Http2Stream
可能会导致超过此限制,但当超过此限制时,新的Http2Stream
实例将被拒绝。当前Http2Stream
会话的数量、标头压缩表的当前内存使用量、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。默认值:10
。maxHeaderListPairs
<number> 设置标头条目的最大数量。这类似于node:http
模块中的server.maxHeadersCount
或request.maxHeadersCount
。最小值为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_ALIGNED
:尝试应用足够的填充以确保包括 9 字节标头在内的总帧长是 8 的倍数。对于每个帧,都有一个由当前流控制状态和设置确定的最大允许填充字节数。如果此最大值小于确保对齐所需的计算量,则使用最大值,并且总帧长不一定按 8 字节对齐。
peerMaxConcurrentStreams
<number> 设置远程对端的最大并发流数量,就像收到了一个SETTINGS
帧一样。如果远程对端设置了自己的maxConcurrentStreams
值,则此值将被覆盖。默认值:100
。maxSessionInvalidFrames
<integer> 设置在会话关闭前将容忍的最大无效帧数。默认值:1000
。maxSessionRejectedStreams
<integer> 设置在会话关闭前将容忍的在创建时被拒绝的最大流数。每次拒绝都与一个NGHTTP2_ENHANCE_YOUR_CALM
错误相关联,该错误应告知对端不要再打开更多流,因此继续打开流被视为行为不端的对端的标志。默认值:100
。settings
<HTTP/2 Settings Object> 连接时发送给远程对端的初始设置。streamResetBurst
<number> 和streamResetRate
<number> 设置传入流重置(RST_STREAM 帧)的速率限制。必须同时设置这两个设置才能生效,默认值分别为 1000 和 33。remoteCustomSettings
<Array> 整数值数组,用于确定设置类型,这些类型包含在接收到的 remoteSettings 的customSettings
属性中。有关允许的设置类型的更多信息,请参阅Http2Settings
对象的customSettings
属性。...options
<Object> 可以提供任何tls.createServer()
选项。对于服务器,通常需要身份选项(pfx
或key
/cert
)。origins
<string[]> 一个源字符串数组,在创建新的服务器Http2Session
后立即在ORIGIN
帧内发送。unknownProtocolTimeout
<number> 指定当触发'unknownProtocol'
事件时服务器应等待的超时时间(毫秒)。如果到那时套接字尚未被销毁,服务器将销毁它。默认值:10000
。strictFieldWhitespaceValidation
<boolean> 如果为true
,则根据 RFC-9113 对 HTTP/2 标头字段名称和值进行严格的前导和尾随空格验证。默认值:true
。
onRequestHandler
<Function> 请参阅兼容性 API- 返回:<Http2SecureServer>
返回一个创建和管理 Http2Session
实例的 tls.Server
实例。
import { createSecureServer } from 'node:http2';
import { readFileSync } from 'node:fs';
const options = {
key: readFileSync('server-key.pem'),
cert: readFileSync('server-cert.pem'),
};
// Create a secure HTTP/2 server
const server = createSecureServer(options);
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html; charset=utf-8',
':status': 200,
});
stream.end('<h1>Hello World</h1>');
});
server.listen(8443);
const http2 = require('node:http2');
const fs = require('node: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; charset=utf-8',
':status': 200,
});
stream.end('<h1>Hello World</h1>');
});
server.listen(8443);
http2.connect(authority[, options][, listener])
#
authority
<string> | <URL> 要连接的远程 HTTP/2 服务器。它必须是具有http://
或https://
前缀、主机名和 IP 端口(如果使用非默认端口)的最小有效 URL 形式。URL 中的 Userinfo(用户 ID 和密码)、路径、查询字符串和片段详细信息将被忽略。options
<Object>maxDeflateDynamicTableSize
<number> 设置用于压缩标头字段的最大动态表大小。默认值:4Kib
。maxSettings
<number> 设置每个SETTINGS
帧的最大设置条目数。允许的最小值为1
。默认值:32
。maxSessionMemory
<number> 设置Http2Session
允许使用的最大内存。该值以兆字节为单位表示,例如1
等于 1 兆字节。允许的最小值为1
。这是一个基于信用的限制,现有的Http2Stream
可能会导致超过此限制,但当超过此限制时,新的Http2Stream
实例将被拒绝。当前Http2Stream
会话的数量、标头压缩表的当前内存使用量、排队等待发送的当前数据以及未确认的PING
和SETTINGS
帧都计入当前限制。默认值:10
。maxHeaderListPairs
<number> 设置标头条目的最大数量。这类似于node:http
模块中的server.maxHeadersCount
或request.maxHeadersCount
。最小值为1
。默认值:128
。maxOutstandingPings
<number> 设置未完成、未确认的 ping 的最大数量。默认值:10
。maxReservedRemoteStreams
<number> 设置客户端在任何给定时间将接受的保留推送流的最大数量。一旦当前保留的推送流数量达到此限制,服务器发送的新推送流将被自动拒绝。允许的最小值为 0。允许的最大值为 232-1。负值将此选项设置为最大允许值。默认值:200
。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_ALIGNED
:尝试应用足够的填充以确保包括 9 字节标头在内的总帧长是 8 的倍数。对于每个帧,都有一个由当前流控制状态和设置确定的最大允许填充字节数。如果此最大值小于确保对齐所需的计算量,则使用最大值,并且总帧长不一定按 8 字节对齐。
peerMaxConcurrentStreams
<number> 设置远程对端的最大并发流数量,就像收到了一个SETTINGS
帧一样。如果远程对端设置了自己的maxConcurrentStreams
值,则此值将被覆盖。默认值:100
。protocol
<string> 用于连接的协议,如果未在authority
中设置。值可以是'http:'
或'https:'
。默认值:'https:'
settings
<HTTP/2 Settings Object> 连接时发送给远程对端的初始设置。remoteCustomSettings
<Array> 整数值数组,用于确定设置类型,这些类型包含在接收到的 remoteSettings 的CustomSettings
属性中。有关允许的设置类型的更多信息,请参阅Http2Settings
对象的CustomSettings
属性。createConnection
<Function> 一个可选的回调函数,接收传递给connect
的URL
实例和options
对象,并返回任何将用作此会话连接的Duplex
流。...options
<Object> 可以提供任何net.connect()
或tls.connect()
选项。unknownProtocolTimeout
<number> 指定当触发'unknownProtocol'
事件时服务器应等待的超时时间(毫秒)。如果到那时套接字尚未被销毁,服务器将销毁它。默认值:10000
。strictFieldWhitespaceValidation
<boolean> 如果为true
,则根据 RFC-9113 对 HTTP/2 标头字段名称和值进行严格的前导和尾随空格验证。默认值:true
。
listener
<Function> 将作为'connect'
事件的一次性监听器注册。- 返回:<ClientHttp2Session>
返回一个 ClientHttp2Session
实例。
import { connect } from 'node:http2';
const client = connect('https://:1234');
/* Use the client */
client.close();
const http2 = require('node:http2');
const client = http2.connect('https://:1234');
/* Use the client */
client.close();
http2.constants
#
RST_STREAM
和 GOAWAY
的错误代码#
值 | 名称 | 常量 |
---|---|---|
0x00 | 无错误 | http2.constants.NGHTTP2_NO_ERROR |
0x01 | 协议错误 | http2.constants.NGHTTP2_PROTOCOL_ERROR |
0x02 | 内部错误 | http2.constants.NGHTTP2_INTERNAL_ERROR |
0x03 | 流控制错误 | http2.constants.NGHTTP2_FLOW_CONTROL_ERROR |
0x04 | 设置超时 | http2.constants.NGHTTP2_SETTINGS_TIMEOUT |
0x05 | 流已关闭 | http2.constants.NGHTTP2_STREAM_CLOSED |
0x06 | 帧大小错误 | http2.constants.NGHTTP2_FRAME_SIZE_ERROR |
0x07 | 拒绝的流 | http2.constants.NGHTTP2_REFUSED_STREAM |
0x08 | 取消 | http2.constants.NGHTTP2_CANCEL |
0x09 | 压缩错误 | http2.constants.NGHTTP2_COMPRESSION_ERROR |
0x0a | 连接错误 | http2.constants.NGHTTP2_CONNECT_ERROR |
0x0b | 保持冷静(Enhance Your Calm) | http2.constants.NGHTTP2_ENHANCE_YOUR_CALM |
0x0c | 安全性不足 | http2.constants.NGHTTP2_INADEQUATE_SECURITY |
0x0d | 需要 HTTP/1.1 | http2.constants.NGHTTP2_HTTP_1_1_REQUIRED |
当服务器在通过 http2server.setTimeout()
设置的给定毫秒数内没有任何活动时,会触发 'timeout'
事件。
http2.getDefaultSettings()
#
返回一个包含 Http2Session
实例默认设置的对象。此方法每次调用时都会返回一个新的对象实例,因此返回的实例可以安全地修改使用。
http2.getPackedSettings([settings])
#
settings
<HTTP/2 Settings Object>- 返回:<Buffer>
返回一个 Buffer
实例,其中包含根据 HTTP/2 规范指定的给定 HTTP/2 设置的序列化表示。这旨在与 HTTP2-Settings
标头字段一起使用。
import { getPackedSettings } from 'node:http2';
const packed = getPackedSettings({ enablePush: false });
console.log(packed.toString('base64'));
// Prints: AAIAAAAA
const http2 = require('node:http2');
const packed = http2.getPackedSettings({ enablePush: false });
console.log(packed.toString('base64'));
// Prints: AAIAAAAA
http2.getUnpackedSettings(buf)
#
buf
<Buffer> | <TypedArray> 打包的设置。- 返回:<HTTP/2 Settings Object>
返回一个 HTTP/2 设置对象,其中包含从给定 Buffer
反序列化的设置,该 Buffer
由 http2.getPackedSettings()
生成。
http2.performServerHandshake(socket[, options])
#
socket
<stream.Duplex>options
<Object> 可以提供任何http2.createServer()
选项。- 返回:<ServerHttp2Session>
从现有套接字创建 HTTP/2 服务器会话。
标头对象#
标头表示为 JavaScript 对象上的自有属性。属性键将被序列化为小写。属性值应该是字符串(如果不是,它们将被强制转换为字符串)或字符串数组(以便为每个标头字段发送多个值)。
const headers = {
':status': '200',
'content-type': 'text-plain',
'ABC': ['has', 'more', 'than', 'one', 'value'],
};
stream.respond(headers);
传递给回调函数的标头对象将具有 null
原型。这意味着像 Object.prototype.toString()
和 Object.prototype.hasOwnProperty()
这样的普通 JavaScript 对象方法将不起作用。
对于传入的标头
: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
、host
、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
标头,值会用 '; ' 连接在一起。 - 对于所有其他标头,值会用 ', ' 连接在一起。
import { createServer } from 'node:http2';
const server = createServer();
server.on('stream', (stream, headers) => {
console.log(headers[':path']);
console.log(headers.ABC);
});
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream, headers) => {
console.log(headers[':path']);
console.log(headers.ABC);
});
原始标头#
在某些 API 中,除了对象格式外,标头也可以作为原始的扁平数组传递或访问,保留了排序和重复键的细节,以匹配原始传输格式。
在这种格式中,键和值在同一个列表中。它*不是*一个元组列表。因此,偶数偏移量是键值,奇数偏移量是相关的值。重复的标头不会被合并,因此每个键值对将单独出现。
这对于诸如代理之类的情况可能很有用,其中现有标头应完全按接收到的方式转发,或者当标头已经以原始格式可用时作为性能优化。
const rawHeaders = [
':status',
'404',
'content-type',
'text/plain',
];
stream.respond(rawHeaders);
敏感标头#
HTTP2 标头可以被标记为敏感,这意味着 HTTP/2 标头压缩算法永远不会对它们进行索引。这对于熵较低且可能被攻击者认为有价值的标头值(例如 Cookie
或 Authorization
)是有意义的。要实现这一点,请将标头名称添加到 [http2.sensitiveHeaders]
属性中,作为数组
const headers = {
':status': '200',
'content-type': 'text-plain',
'cookie': 'some-cookie',
'other-sensitive-header': 'very secret data',
[http2.sensitiveHeaders]: ['cookie', 'other-sensitive-header'],
};
stream.respond(headers);
对于某些标头,例如 Authorization
和短的 Cookie
标头,此标志是自动设置的。
此属性也为接收到的标头设置。它将包含所有标记为敏感的标头的名称,包括那些自动标记的标头。
对于原始标头,这仍然应该作为数组上的一个属性来设置,比如 rawHeadersArray[http2.sensitiveHeaders] = ['cookie']
,而不是作为数组本身内的一个单独的键值对。
设置对象#
http2.getDefaultSettings()
、http2.getPackedSettings()
、http2.createServer()
、http2.createSecureServer()
、http2session.settings()
、http2session.localSettings
和 http2session.remoteSettings
API 要么返回,要么作为输入接收一个对象,该对象定义了 Http2Session
对象的配置设置。这些对象是包含以下属性的普通 JavaScript 对象。
headerTableSize
<number> 指定用于标头压缩的最大字节数。允许的最小值为 0。允许的最大值为 232-1。默认值:4096
。enablePush
<boolean> 如果允许在Http2Session
实例上使用 HTTP/2 推送流,则指定为true
。默认值:true
。initialWindowSize
<number> 指定用于流级流控制的*发送方*初始窗口大小(以字节为单位)。允许的最小值为 0。允许的最大值为 232-1。默认值:65535
。maxFrameSize
<number> 指定最大帧有效载荷的大小(以字节为单位)。允许的最小值为 16,384。允许的最大值为 224-1。默认值:16384
。maxConcurrentStreams
<number> 指定Http2Session
上允许的最大并发流数量。没有默认值,这意味着,至少在理论上,一个Http2Session
中可以同时打开 232-1 个流。最小值为 0。允许的最大值为 232-1。默认值:4294967295
。maxHeaderListSize
<number> 指定将接受的标头列表的最大大小(未压缩的八位字节)。允许的最小值为 0。允许的最大值为 232-1。默认值:65535
。maxHeaderSize
<number>maxHeaderListSize
的别名。enableConnectProtocol
<boolean> 指定是否启用由 RFC 8441 定义的“扩展连接协议”。此设置仅在由服务器发送时有意义。一旦为给定的Http2Session
启用了enableConnectProtocol
设置,就无法禁用它。默认值:false
。customSettings
<Object> 指定了尚未在 node 和底层库中实现的附加设置。对象的键定义了设置类型的数值(如 [RFC 7540] 建立的“HTTP/2 SETTINGS”注册表中所定义),值则为设置的实际数值。设置类型必须是 1 到 2^16-1 范围内的整数。它不应该是 node 已经处理的设置类型,即目前应大于 6,尽管这不是一个错误。值必须是 0 到 2^32-1 范围内的无符号整数。目前,最多支持 10 个自定义设置。它仅支持发送 SETTINGS,或接收在服务器或客户端对象的remoteCustomSettings
选项中指定的设置值。不要将customSettings
机制用于与原生处理的设置接口混合的设置 ID,以防将来 node 版本中某个设置被原生支持。
设置对象上的所有其他属性都将被忽略。
错误处理#
使用 node:http2
模块时可能会出现几种类型的错误条件
当传入不正确的参数、选项或设置值时,会发生验证错误。这些错误总是通过同步的 throw
报告。
当在不正确的时间尝试执行某个操作时(例如,在流关闭后尝试在其上发送数据),会发生状态错误。这些错误将通过同步的 throw
或 Http2Stream
、Http2Session
或 HTTP/2 服务器对象上的 'error'
事件报告,具体取决于错误发生的位置和时间。
当 HTTP/2 会话意外失败时,会发生内部错误。这些错误将通过 Http2Session
或 HTTP/2 服务器对象上的 'error'
事件报告。
当违反各种 HTTP/2 协议约束时,会发生协议错误。这些错误将通过同步的 throw
或 Http2Stream
、Http2Session
或 HTTP/2 服务器对象上的 'error'
事件报告,具体取决于错误发生的位置和时间。
标头名称和值中的无效字符处理#
HTTP/2 实现对 HTTP 标头名称和值中的无效字符的处理比 HTTP/1 实现更严格。
标头字段名称*不区分大小写*,并在网络上传输时严格作为小写字符串。Node.js 提供的 API 允许将标头名称设置为混合大小写字符串(例如 Content-Type
),但在传输时会将其转换为小写(例如 content-type
)。
标头字段名称*必须仅*包含以下一个或多个 ASCII 字符:a
-z
、A
-Z
、0
-9
、!
、#
、$
、%
、&
、'
、*
、+
、-
、.
、^
、_
、`
(反引号)、|
和 ~
。
在 HTTP 标头字段名称中使用无效字符将导致流因协议错误而关闭。
标头字段值的处理更为宽松,但*不应*包含换行符或回车符,并且*应*限制为 US-ASCII 字符,根据 HTTP 规范的要求。
客户端上的推送流#
要在客户端接收推送流,请在 ClientHttp2Session
上为 'stream'
事件设置一个监听器
import { connect } from 'node:http2';
const client = connect('https://');
client.on('stream', (pushedStream, requestHeaders) => {
pushedStream.on('push', (responseHeaders) => {
// Process response headers
});
pushedStream.on('data', (chunk) => { /* handle pushed data */ });
});
const req = client.request({ ':path': '/' });
const http2 = require('node:http2');
const client = http2.connect('https://');
client.on('stream', (pushedStream, requestHeaders) => {
pushedStream.on('push', (responseHeaders) => {
// Process response headers
});
pushedStream.on('data', (chunk) => { /* handle pushed data */ });
});
const req = client.request({ ':path': '/' });
支持 CONNECT
方法#
CONNECT
方法用于允许将 HTTP/2 服务器用作 TCP/IP 连接的代理。
一个简单的 TCP 服务器
import { createServer } from 'node:net';
const server = createServer((socket) => {
let name = '';
socket.setEncoding('utf8');
socket.on('data', (chunk) => name += chunk);
socket.on('end', () => socket.end(`hello ${name}`));
});
server.listen(8000);
const net = require('node: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 代理
import { createServer, constants } from 'node:http2';
const { NGHTTP2_REFUSED_STREAM, NGHTTP2_CONNECT_ERROR } = constants;
import { connect } from 'node:net';
const proxy = 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 = connect(auth.port, auth.hostname, () => {
stream.respond();
socket.pipe(stream);
stream.pipe(socket);
});
socket.on('error', (error) => {
stream.close(NGHTTP2_CONNECT_ERROR);
});
});
proxy.listen(8001);
const http2 = require('node:http2');
const { NGHTTP2_REFUSED_STREAM } = http2.constants;
const net = require('node: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 客户端
import { connect, constants } from 'node:http2';
const client = connect('https://: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:8000',
});
req.on('response', (headers) => {
console.log(headers[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');
const http2 = require('node:http2');
const client = http2.connect('https://: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:8000',
});
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');
扩展 CONNECT
协议#
RFC 8441 定义了一个对 HTTP/2 的“扩展 CONNECT 协议”扩展,可用于引导使用 CONNECT
方法的 Http2Stream
作为其他通信协议(例如 WebSockets)的隧道。
HTTP/2 服务器通过使用 enableConnectProtocol
设置来启用扩展 CONNECT 协议
import { createServer } from 'node:http2';
const settings = { enableConnectProtocol: true };
const server = createServer({ settings });
const http2 = require('node:http2');
const settings = { enableConnectProtocol: true };
const server = http2.createServer({ settings });
一旦客户端从服务器接收到指示可以使用扩展 CONNECT 的 SETTINGS
帧,它就可以发送使用 ':protocol'
HTTP/2 伪标头的 CONNECT
请求
import { connect } from 'node:http2';
const client = connect('https://:8080');
client.on('remoteSettings', (settings) => {
if (settings.enableConnectProtocol) {
const req = client.request({ ':method': 'CONNECT', ':protocol': 'foo' });
// ...
}
});
const http2 = require('node:http2');
const client = http2.connect('https://:8080');
client.on('remoteSettings', (settings) => {
if (settings.enableConnectProtocol) {
const req = client.request({ ':method': 'CONNECT', ':protocol': 'foo' });
// ...
}
});
兼容性 API#
兼容性 API 的目标是在使用 HTTP/2 时提供与 HTTP/1 相似的开发者体验,从而可以开发同时支持 HTTP/1 和 HTTP/2 的应用程序。此 API 仅针对 HTTP/1 的**公共 API**。然而,许多模块使用内部方法或状态,这些*不受支持*,因为它是一个完全不同的实现。
以下示例使用兼容性 API 创建一个 HTTP/2 服务器
import { createServer } from 'node:http2';
const server = createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('ok');
});
const http2 = require('node: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; charset=utf-8' });
res.end('ok');
});
要创建混合的 HTTPS 和 HTTP/2 服务器,请参阅 ALPN 协商部分。不支持从非 tls HTTP/1 服务器升级。
HTTP/2 兼容性 API 由 Http2ServerRequest
和 Http2ServerResponse
组成。它们旨在与 HTTP/1 的 API 兼容,但它们不隐藏协议之间的差异。例如,HTTP 状态码的状态消息被忽略。
ALPN 协商#
ALPN 协商允许在同一个套接字上同时支持 HTTPS 和 HTTP/2。req
和 res
对象可以是 HTTP/1 或 HTTP/2,应用程序**必须**将自己限制在 HTTP/1 的公共 API 内,并检测是否可以使用 HTTP/2 的更高级功能。
以下示例创建了一个同时支持两种协议的服务器
import { createSecureServer } from 'node:http2';
import { readFileSync } from 'node:fs';
const cert = readFileSync('./cert.pem');
const key = readFileSync('./key.pem');
const server = createSecureServer(
{ cert, key, allowHTTP1: true },
onRequest,
).listen(8000);
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,
}));
}
const { createSecureServer } = require('node:http2');
const { readFileSync } = require('node: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 上的工作方式相同。
类:http2.Http2ServerRequest
#
Http2ServerRequest
对象由 http2.Server
或 http2.SecureServer
创建,并作为第一个参数传递给 'request'
事件。它可用于访问请求状态、标头和数据。
事件:'aborted'
#
每当 Http2ServerRequest
实例在通信中途异常中止时,就会触发 'aborted'
事件。
只有在 Http2ServerRequest
的可写端尚未结束时,才会触发 'aborted'
事件。
事件:'close'
#
表示底层的 Http2Stream
已关闭。与 'end'
一样,此事件每个响应只发生一次。
request.authority
#
- 类型:<string>
请求的 authority 伪标头字段。因为 HTTP/2 允许请求设置 :authority
或 host
,所以如果存在 req.headers[':authority']
,则此值派生自它。否则,它派生自 req.headers['host']
。
request.destroy([error])
#
error
<Error>
在接收到 Http2ServerRequest
的 Http2Stream
上调用 destroy()
。如果提供了 error
,则会触发一个 'error'
事件,并且 error
会作为参数传递给该事件的任何监听器。
如果流已经被销毁,则不执行任何操作。
request.headers
#
- 类型:<Object>
请求/响应的标头对象。
标头名称和值的键值对。标头名称是小写的。
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*/*' }
console.log(request.headers);
请参阅 HTTP/2 标头对象。
在 HTTP/2 中,请求路径、主机名、协议和方法表示为以 :
字符为前缀的特殊标头(例如 ':path'
)。这些特殊标头将包含在 request.headers
对象中。必须注意不要无意中修改这些特殊标头,否则可能会发生错误。例如,从请求中删除所有标头将导致错误发生
removeAllHeaders(request.headers);
assert(request.url); // Fails because the :path header has been removed
request.httpVersion
#
- 类型:<string>
对于服务器请求,是客户端发送的 HTTP 版本。对于客户端响应,是所连接服务器的 HTTP 版本。返回 '2.0'
。
同时 message.httpVersionMajor
是第一个整数,message.httpVersionMinor
是第二个。
request.rawHeaders
#
接收到的原始请求/响应标头列表,完全按原样。
// 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);
request.setTimeout(msecs, callback)
#
msecs
<number>callback
<Function>- 返回:<http2.Http2ServerRequest>
将 Http2Stream
的超时值设置为 msecs
。如果提供了回调,则将其添加为响应对象上 'timeout'
事件的监听器。
如果没有为请求、响应或服务器添加 'timeout'
监听器,那么当 Http2Stream
超时时,它们将被销毁。如果为请求、响应或服务器的 'timeout'
事件分配了处理程序,则必须显式处理超时的套接字。
request.socket
#
返回一个充当 net.Socket
(或 tls.TLSSocket
)的 Proxy
对象,但会根据 HTTP/2 逻辑应用 getter、setter 和方法。
destroyed
、readable
和 writable
属性将从 request.stream
中检索和设置。
destroy
、emit
、end
、on
和 once
方法将在 request.stream
上调用。
setTimeout
方法将在 request.stream.session
上调用。
pause
、read
、resume
和 write
将抛出一个带有代码 ERR_HTTP2_NO_SOCKET_MANIPULATION
的错误。更多信息请参见 Http2Session
和套接字。
所有其他交互将直接路由到套接字。对于 TLS 支持,请使用 request.socket.getPeerCertificate()
获取客户端的身份验证详细信息。
request.url
#
- 类型:<string>
请求 URL 字符串。这仅包含实际 HTTP 请求中存在的 URL。如果请求是
GET /status?name=ryan HTTP/1.1
Accept: text/plain
那么 request.url
将是
'/status?name=ryan'
要将 URL 解析为其各个部分,可以使用 new URL()
$ node
> new URL('/status?name=ryan', 'http://example.com')
URL {
href: 'http://example.com/status?name=ryan',
origin: 'http://example.com',
protocol: 'http:',
username: '',
password: '',
host: 'example.com',
hostname: 'example.com',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
类:http2.Http2ServerResponse
#
- 继承自:<Stream>
此对象由 HTTP 服务器内部创建,而非由用户创建。它作为第二个参数传递给 'request'
事件。
事件:'close'
#
表示底层的 Http2Stream
在 response.end()
被调用或能够刷新之前已终止。
事件:'finish'
#
当响应已发送时触发。更具体地说,此事件在响应标头和正文的最后一部分已移交给 HTTP/2 多路复用以通过网络传输时触发。这并不意味着客户端已经收到了任何东西。
在此事件之后,响应对象上将不再触发任何事件。
response.addTrailers(headers)
#
headers
<Object>
此方法向响应添加 HTTP 尾部标头(位于消息末尾的标头)。
尝试设置包含无效字符的标头字段名称或值将导致抛出 TypeError
。
response.appendHeader(name, value)
#
name
<string>value
<string> | <string[]>
向标头对象追加单个标头值。
如果值是数组,这等同于多次调用此方法。
如果该标头之前没有值,这等同于调用 response.setHeader()
。
尝试设置包含无效字符的标头字段名称或值将导致抛出 TypeError
。
// Returns headers including "set-cookie: a" and "set-cookie: b"
const server = http2.createServer((req, res) => {
res.setHeader('set-cookie', 'a');
res.appendHeader('set-cookie', 'b');
res.writeHead(200);
res.end('ok');
});
response.createPushResponse(headers, callback)
#
headers
<HTTP/2 Headers Object> 描述 Headers 的对象callback
<Function> 在http2stream.pushStream()
完成后调用一次,或者在尝试创建推送的Http2Stream
失败或被拒绝时,或者在调用http2stream.pushStream()
方法之前Http2ServerRequest
的状态已关闭时调用err
<Error>res
<http2.Http2ServerResponse> 新创建的Http2ServerResponse
对象
使用给定的标头调用 http2stream.pushStream()
,如果成功,则将给定的 Http2Stream
包装在一个新创建的 Http2ServerResponse
中作为回调参数。当 Http2ServerRequest
关闭时,回调会以错误 ERR_HTTP2_INVALID_STREAM
被调用。
response.end([data[, encoding]][, callback])
#
data
<string> | <Buffer> | <Uint8Array>encoding
<string>callback
<Function>- 返回:<this>
此方法向服务器发出信号,表示所有响应标头和正文都已发送;服务器应认为此消息已完成。必须对每个响应调用 response.end()
方法。
如果指定了 data
,则等同于调用 response.write(data, encoding)
后跟 response.end(callback)
。
如果指定了 callback
,它将在响应流完成时被调用。
response.finished
#
response.writableEnded
。- 类型:<boolean>
布尔值,指示响应是否已完成。初始为 false
。在 response.end()
执行后,该值将为 true
。
response.getHeader(name)
#
读出已经排队但尚未发送给客户端的标头。名称不区分大小写。
const contentType = response.getHeader('content-type');
response.getHeaderNames()
#
- 返回:<string[]>
返回一个包含当前传出标头的唯一名称的数组。所有标头名称都是小写的。
response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);
const headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']
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'] }
response.hasHeader(name)
#
如果由 name
标识的标头当前设置在传出标头中,则返回 true
。标头名称匹配不区分大小写。
const hasContentType = response.hasHeader('content-type');
response.removeHeader(name)
#
name
<string>
删除已排队等待隐式发送的标头。
response.removeHeader('Content-Encoding');
response.sendDate
#
- 类型:<boolean>
当为 true 时,如果 Date 标头尚未出现在标头中,则会自动生成并发送在响应中。默认为 true。
这只应在测试时禁用;HTTP 要求响应中包含 Date 标头。
response.setHeader(name, value)
#
name
<string>value
<string> | <string[]>
为隐式标头设置单个标头值。如果此标头已存在于将要发送的标头中,其值将被替换。在此处使用字符串数组以发送多个同名标头。
response.setHeader('Content-Type', 'text/html; charset=utf-8');
或
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; charset=utf-8');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('ok');
});
response.setTimeout(msecs[, callback])
#
msecs
<number>callback
<Function>- 返回:<http2.Http2ServerResponse>
将 Http2Stream
的超时值设置为 msecs
。如果提供了回调,则将其添加为响应对象上 'timeout'
事件的监听器。
如果没有为请求、响应或服务器添加 'timeout'
监听器,那么当 Http2Stream
超时时,它们将被销毁。如果为请求、响应或服务器的 'timeout'
事件分配了处理程序,则必须显式处理超时的套接字。
response.socket
#
返回一个充当 net.Socket
(或 tls.TLSSocket
)的 Proxy
对象,但会根据 HTTP/2 逻辑应用 getter、setter 和方法。
destroyed
、readable
和 writable
属性将从 response.stream
中检索和设置。
destroy
、emit
、end
、on
和 once
方法将在 response.stream
上调用。
setTimeout
方法将在 response.stream.session
上调用。
pause
、read
、resume
和 write
将抛出一个带有代码 ERR_HTTP2_NO_SOCKET_MANIPULATION
的错误。更多信息请参见 Http2Session
和套接字。
所有其他交互将直接路由到套接字。
import { createServer } from 'node:http2';
const server = 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);
const http2 = require('node: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);
response.statusCode
#
- 类型:<number>
当使用隐式标头时(不显式调用 response.writeHead()
),此属性控制在标头刷新时将发送给客户端的状态码。
response.statusCode = 404;
在响应标头发送给客户端后,此属性指示已发送的状态码。
response.writableEnded
#
- 类型:<boolean>
在 response.end()
被调用后为 true
。此属性不指示数据是否已刷新,为此请改用 writable.writableFinished
。
response.write(chunk[, encoding][, callback])
#
chunk
<string> | <Buffer> | <Uint8Array>encoding
<string>callback
<Function>- 返回:<boolean>
如果调用此方法时 response.writeHead()
尚未被调用,它将切换到隐式标头模式并刷新隐式标头。
这会发送响应正文的一个块。此方法可以多次调用以提供正文的连续部分。
在 node:http
模块中,当请求是 HEAD 请求时,会省略响应正文。类似地,204
和 304
响应*不得*包含消息体。
chunk
可以是字符串或缓冲区。如果 chunk
是字符串,第二个参数指定如何将其编码为字节流。默认情况下,encoding
是 'utf8'
。当此数据块被刷新时,将调用 callback
。
这是原始的 HTTP 正文,与可能使用的更高级别的多部分正文编码无关。
第一次调用 response.write()
时,它将把缓冲的标头信息和正文的第一个块发送给客户端。第二次调用 response.write()
时,Node.js 假定数据将以流式传输,并单独发送新数据。也就是说,响应被缓冲到正文的第一个块。
如果所有数据都成功刷新到内核缓冲区,则返回 true
。如果全部或部分数据被排队在用户内存中,则返回 false
。当缓冲区再次空闲时,将触发 'drain'
事件。
response.writeContinue()
#
向客户端发送状态码 100 Continue
,表示应发送请求正文。请参阅 Http2Server
和 Http2SecureServer
上的 'checkContinue'
事件。
response.writeEarlyHints(hints)
#
hints
<Object>
向客户端发送状态码 103 Early Hints
及 Link 标头,指示用户代理可以预加载/预连接链接的资源。hints
是一个包含要与早期提示消息一起发送的标头值的对象。
示例
const earlyHintsLink = '</styles.css>; rel=preload; as=style';
response.writeEarlyHints({
'link': earlyHintsLink,
});
const earlyHintsLinks = [
'</styles.css>; rel=preload; as=style',
'</scripts.js>; rel=preload; as=script',
];
response.writeEarlyHints({
'link': earlyHintsLinks,
});
response.writeHead(statusCode[, statusMessage][, headers])
#
statusCode
<number>statusMessage
<string>headers
<HTTP/2 Headers Object> | <HTTP/2 Raw Headers>- 返回:<http2.Http2ServerResponse>
向请求发送响应标头。状态码是一个 3 位的 HTTP 状态码,如 404
。最后一个参数 headers
是响应标头。
返回对 Http2ServerResponse
的引用,以便可以链式调用。
为了与 HTTP/1 兼容,可以传递一个人类可读的 statusMessage
作为第二个参数。但是,由于 statusMessage
在 HTTP/2 中没有意义,该参数将没有效果,并且会发出一个进程警告。
const body = 'hello world';
response.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/plain; charset=utf-8',
});
Content-Length
以字节为单位,而不是字符。可以使用 Buffer.byteLength()
API 来确定给定编码中的字节数。在出站消息中,Node.js 不检查 Content-Length 是否与正在传输的正文长度相等。但是,在接收消息时,Node.js 会自动拒绝 Content-Length
与实际有效载荷大小不匹配的消息。
在调用 response.end()
之前,此方法最多只能对一条消息调用一次。
如果在调用此方法之前调用了 response.write()
或 response.end()
,则将计算隐式/可变标头并调用此函数。
当使用 response.setHeader()
设置了标头后,它们将与传递给 response.writeHead()
的任何标头合并,其中传递给 response.writeHead()
的标头具有优先权。
// Returns content-type = text/plain
const server = http2.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('ok');
});
尝试设置包含无效字符的标头字段名称或值将导致抛出 TypeError
。
收集 HTTP/2 性能指标#
可以使用 Performance Observer API 来收集每个 Http2Session
和 Http2Stream
实例的基本性能指标。
import { PerformanceObserver } from 'node: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'] });
const { PerformanceObserver } = require('node: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>'server'
或'client'
,用于标识Http2Session
的类型。
关于 :authority
和 host
的说明#
HTTP/2 要求请求必须有 :authority
伪标头或 host
标头。直接构建 HTTP/2 请求时优先使用 :authority
,从 HTTP/1 转换时(例如在代理中)优先使用 host
。
如果 :authority
不存在,兼容性 API 会回退到 host
。更多信息请参阅 request.authority
。但是,如果您不使用兼容性 API(或直接使用 req.headers
),则需要自己实现任何回退行为。