GitHub - currentspace/http3

GitHub

4 min read Original article ↗

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
  • Explicit runtime selection: fast, portable, or auto
  • 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

Prebuilt native binaries are currently published for Linux x64/arm64 (glibc) and macOS arm64. Other platforms may fall back to local native compilation; 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(443, '0.0.0.0');

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 });

Runtime modes

Every QUIC-capable API accepts:

  • runtimeMode: 'auto' | 'fast' | 'portable'
  • 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.

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 the client (HTTP/3 or raw QUIC) entirely on a wasm32-wasip1 build of the same quiche + BoringSSL protocol core, with no native .node addon in the process:

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

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

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

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

Examples

Start Here

Deployment and Operations

Contributors and Maintainers