@currentspace/http3

中文文档
1.0.0发布于 2026/11/01MITTypeScriptCommonJS零依赖构建来源已验证

HTTP/3 server and client for Node.js, powered by Cloudflare quiche

原始使用文档
文档目录16 节
  1. Features
  2. Install
  3. Quick server example
  4. Local development
  5. Quick client example
  6. Streaming and cancellation
  7. Runtime modes
  8. WASM runtime
  9. Raw QUIC mTLS
  10. Quick QUIC server
  11. Quick QUIC client
  12. Compatibility surfaces
  13. Examples
  14. Start Here
  15. Deployment and Operations
  16. Contributors and Maintainers

@currentspace/http3

HTTP/3, HTTP/2, and raw QUIC server/client package for Node.js 24+, powered by Rust + quiche.

Features

  • HTTP/3 server and client over QUIC/UDP
  • HTTP/2 fallback over TLS/TCP on the same listener
  • Raw QUIC: bidirectional streams, datagrams, session resumption, custom ALPN
  • Runtime selection: auto, fast, portable, or wasm
  • Platform-native I/O: kqueue (macOS), io_uring (Linux fast path), poll (Linux portable path)
  • WASM runtime (runtimeMode: 'wasm') for HTTP/3 and raw QUIC clients, plus a Node-only WASM server — no native .node addon required, and confirmed running inside real Cloudflare workerd
  • fetch/SSE/EventSource adapters
  • Express compatibility via @currentspace/http3/express

Install

npm install @currentspace/http3

Version 1.0.0 adds automatic WASM fallback, bounded large writes, facade runtime metadata, and native packages for Linux musl and Intel macOS. Earlier 0.9.9 installations require explicit WASM when a native addon is unavailable.

Keep optional dependencies enabled for native performance. If the native addon cannot load, the default auto mode selects the bundled WASM runtime and emits WARN_HTTP3_RUNTIME_FALLBACK. The root package contains JavaScript, declarations, WASM, and the CLI; it does not bundle native binaries, docs, or examples.

PlatformNative package targetWhen the addon cannot load
macOS arm64 / x64darwin-arm64 / darwin-x64WASM
Linux glibc arm64 / x64linux-arm64-gnu / linux-x64-gnuWASM
Linux musl arm64 / x64 (Alpine)linux-arm64-musl / linux-x64-muslWASM
WindowsNoneWASM
Other Node platformsNone in the release matrixWASM; platform qualification varies

All six native targets use matching 1.0.0 sidecars. There is no install-time compiler fallback. See docs/SUPPORT_MATRIX.md.

Quick server example

import { createSecureServer } from '@currentspace/http3';

const server = createSecureServer({
  key: process.env.TLS_KEY_PEM,
  cert: process.env.TLS_CERT_PEM,
}, (stream, headers) => {
  stream.respond({ ':status': '200', 'content-type': 'text/plain' });
  stream.end(`hello ${String(headers[':path'] ?? '/')}`);
});

server.listen({ port: 443 }); // Dual-stack ::, all interfaces.

Local development

In 0.9.7+, npx @currentspace/http3 dev-cert --out .certs --trust creates a constrained localhost CA, installs local trust explicitly, and issues a certificate. From a built source checkout use node bin/http3.cjs dev-cert --out .certs --trust. Use key.pem/cert.pem on the server and set NODE_EXTRA_CA_CERTS=/absolute/path/.certs/ca.pem before starting Node clients. This library's native/WASM clients need an explicit ca option instead.

Chrome also needs --origin-to-force-quic-on=localhost:1 for locally trusted QUIC. The unused port enables the local-root exception; the application still negotiates H3 through Alt-Svc. Listeners default to dual-stack :: (all interfaces), so localhost works over IPv4 and IPv6. See the local development guide for trust removal, server configuration, browser launch commands, and loopback-only binding.

Quick client example

import { connectAsync } from '@currentspace/http3';

const session = await connectAsync('example.com:443');
const stream = session.request({
  ':method': 'GET',
  ':path': '/',
  ':authority': 'example.com',
  ':scheme': 'https',
}, { endStream: true });

Streaming and cancellation

H3 request and response bodies apply receive-credit flow control in native and WASM runtimes. Pausing a reader eventually backpressures the peer; other streams on the connection can continue. QUIC receive windows and transport queues are separate from Node's readable high-water mark.

Use pipeline() or wait for drain when write() returns false. Write callbacks, drain, and finish describe local write admission, not receipt or acknowledgement by the peer. Destroying an unfinished client stream cancels it remotely and rejects pending writes; normal duplex completion does not reset it.

Runtime modes

Every QUIC-capable API accepts:

  • runtimeMode: 'auto' | 'fast' | 'portable' | 'wasm'
  • fallbackPolicy: 'error' | 'warn-and-fallback'
  • onRuntimeEvent(info)

Returned client sessions and server objects expose runtimeInfo, and auto fallback also emits a process warning with code WARN_HTTP3_RUNTIME_FALLBACK. This includes the Node facade returned by createNodeServerFactory.

auto prefers native, retaining the Linux fast → portable fallback when io_uring is unavailable. If the binding itself cannot load, auto with the default warn-and-fallback policy selects WASM before constructing native state. The warning identifies the OS, architecture, Linux libc, and loader failure. runtimeInfo.reasonCode is native-binding-unavailable for this case. Explicit fast/portable, or auto with fallbackPolicy: 'error', instead fail with ERR_HTTP3_RUNTIME_UNSUPPORTED. Explicit WASM never probes native loading.

import { connectQuicAsync } from '@currentspace/http3';

const session = await connectQuicAsync('https://sfu:9080', {
  alpn: ['sfu-repl'],
  rejectUnauthorized: false,
  runtimeMode: 'auto',
  fallbackPolicy: 'warn-and-fallback',
});

console.log(session.runtimeInfo);

See docs/RUNTIME_MODES.md for the deployment matrix, capability requirements, Docker guidance, topology policy, and the raw endpoint contract.

Client topology is now explicit in the implementation:

  • raw QUIC fast clients share one worker and one local UDP port per bind family
  • H3 fast clients share one worker and one local UDP port per bind family
  • macOS portable mode keeps the same shared client-worker ownership model on top of kqueue
  • QUIC and H3 servers remain one-worker-per-port architectures

Use the built-in benchmarks to inspect both runtime selection and internal reactor counters:

npm run bench:quic -- --profile smoke
npm run bench:h3 -- --profile smoke

WASM runtime

runtimeMode: 'wasm' runs HTTP/3 and raw QUIC clients and Node servers on a wasm32-wasip1 build of the same quiche + BoringSSL protocol core, with no native .node addon:

import { connectAsync } from '@currentspace/http3';

const session = await connectAsync('example.com:443', { runtimeMode: 'wasm' });

Large Node stream writes, including res.end(buffer), are admitted in bounded slices under WASM. Continue to respect writable backpressure; concurrent work still shares a finite WASM heap. Native writes retain their existing path.

Consumer measurements on 2026-10-30, using 0.9.9 on macOS arm64 / Node 26.13 with a native client, found about 5,060–5,270 requests/s under WASM versus 10,500–12,300 native portable for 1,000 small GETs at concurrency 50. Streamed 32 MiB downloads measured 91–93 MiB/s versus 836–933 MiB/s. These describe those workloads, not performance guarantees on other hosts. Use native packages for throughput-sensitive deployments; WASM keeps development and smaller workloads usable without an addon.

The server side (Http3SecureServer.listen() / QuicServer.listen()) also supports runtimeMode: 'wasm', Node-only. The client build has additionally been verified running inside real Cloudflare workerd — see examples/workerd-client; the only remaining blocker to a real workerd deployment is that Workers has no outbound UDP client socket API yet (cloudflare/workerd#4463).

See docs/WASM_RUNTIME.md for the full usage guide and current Node/workerd support matrix, and docs/WASM_CLIENT_PLAN.md for the design.

Raw QUIC mTLS

  • Raw QUIC clients can use mTLS through the stable public cert and key options on connectQuic() and connectQuicAsync().
  • Raw QUIC servers support explicit client certificate policy with clientAuth, defaulting to require when a verification ca is configured.
  • Raw QUIC server sessions expose the verified peer certificate so applications can inspect or pin exact client certificates with Node's X509Certificate API.

See CHANGELOG.md for release notes and docs/RELEASE_EVIDENCE.md for the current release's audit ledger and caveats.

Quick QUIC server

import { createQuicServer } from '@currentspace/http3';

const server = createQuicServer({
  key: process.env.TLS_KEY_PEM,
  cert: process.env.TLS_CERT_PEM,
});

server.on('session', (session) => {
  session.on('stream', (stream) => {
    stream.pipe(stream); // echo
  });
});

await server.listen(4433, '0.0.0.0');

Quick QUIC client

import { connectQuicAsync } from '@currentspace/http3';

const session = await connectQuicAsync('127.0.0.1:4433', {
  rejectUnauthorized: false,
});

const stream = session.openStream();
stream.end(Buffer.from('hello QUIC'));

const chunks: Buffer[] = [];
stream.on('data', (c) => chunks.push(c));
stream.on('end', () => console.log(Buffer.concat(chunks).toString()));

Compatibility surfaces

The experimental Node-style server factory, introduced in 0.9.4, supports Fastify integration. Version 0.9.5 adds the compatibility fixes used by the Next.js custom-server example.

  • @currentspace/http3 - canonical API.
  • @currentspace/http3/parity - http2-style aliases for migrations.
  • @currentspace/http3/h3 - HTTP/3-specific extension namespace.

The package root also exports createNodeServerFactory and createExpressHandler. Subpath declarations use typesVersions for legacy TypeScript moduleResolution: "node"; modern Node16/NodeNext/bundler resolution continues to use exports. No ambient module declarations are required.

Since 0.9.7, native and WASM H3 request bodies are flow-controlled: a slow or paused handler holds the client back. A 4 MiB upload can stream through a slow handler with the default maxBufferedRequestBytes: 1024 * 1024 (1 MiB). This option caps unread bytes buffered in the transport stream, including data already in flight when reading pauses; it is not a total upload-size limit. Exceeding the cap resets the stream, but large streaming uploads do not normally need a higher value. Framework body-size limits still apply. See request buffering.

Examples

Start Here

Deployment and Operations

Contributors and Maintainers

版本与发布记录

@currentspace/http3 共发布 30 个版本,首次发布于 2026/03/13;过去 12 个月发布了 30 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.0.0latest2026/11/012 天前
0.9.92026/10/313 天前
0.9.82026/10/303 天前
0.9.72026/10/304 天前
0.9.62026/10/304 天前
0.9.52026/10/304 天前

其他发布通道:canary → 0.8.3。

关于 @currentspace/http3 的常见问题

@currentspace/http3 是什么?

基于Node.js的HTTP/3服务器和客户端,由Cloudflare quiche提供支持

如何安装 @currentspace/http3?

在项目目录运行 npm install @currentspace/http3,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 http3,可以用 npx http3 直接运行。

@currentspace/http3 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@currentspace/http3 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@currentspace/http3 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@currentspace/http3 可以商用吗?

@currentspace/http3 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@currentspace/http3 还在维护吗?

最新版本 1.0.0 发布于 2026/11/01(2 天前);至今共发布 30 个版本,其中过去 12 个月发布了 30 个;首次发布于 2026/03/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。