node:http/https/http2: raise Node v26.3.0 compat to ~93% (timeouts, pipelining, clientError, upgrade/CONNECT/trailers, h2 session errors, limits and flow control, net.Socket server sockets) and sync the upstream suites#32488
Draft
cirospaciari wants to merge 11 commits into
Conversation
…pt, keep-alive idle close, async pipelining, llhttp-strict parsing in node mode, upgrade-with-body, CONNECT tunnels, trailers, per-server parser options, SNI accessor All new parser/lifecycle behavior is gated on the node:http compat flags so Bun.serve keeps its existing lenient parser and fast paths unchanged.
…ientError parity, pipelined response queue, maxRequestsPerSocket, upgrade/CONNECT handoff, trailers, agent and client fixes, https TLS option forwarding (pfx, min/maxVersion, ALPN props), SNI servername, domain binding, abort and half-open socket lifecycle
…imits, settings parity (empty initial frame, customSettings, enableConnectProtocol), write backpressure with deferred completion, client request queueing and AbortSignal, respondWithFile fd ownership, AsyncLocalStorage context, allowHTTP1 fallback headers, trailers ordering
Vendor 102 missing upstream tests (64 passing now, 38 recorded as not yet passing in expectations.txt), resync 84 drifted vendored files to v26.3.0 content, drop 49 expectations entries that now pass (including the test-stream-pipeline.js skip), and update Bun-authored assertions that relied on the old divergent error codes/messages.
Collaborator
|
Updated 11:36 PM PT - Jun 18th, 2026
❌ @cirospaciari, your commit 4a12f3e has 3 failures in
🧪 To try this PR locally: bunx bun-pr 32488That installs a local version of the PR into your bun-32488 --bun |
Contributor
|
Found 17 issues this PR may fix:
🤖 Generated with Claude Code |
Contributor
|
This PR may be a duplicate of:
🤖 Generated with Claude Code |
…nel data loss, h2 destroy stream errors - node:http server: a client FIN no longer tears the connection down while pipelined responses are still queued behind the in-flight one; the loop-level force-close is disabled for node compat sockets and the connection is shut down once the pipeline drains (test-http-server.js). With nothing queued the FIN still closes the connection right away, like Node's socket.end(). - node:http upgrade with a body: reading the request no longer flips the raw socket into flowing mode, so tunnel bytes arriving before the 'upgrade' listener attaches its own 'data' handler are buffered instead of discarded (test-http-upgrade-server-with-body*.mjs timed out on optimized builds). - node:http2: session.destroy(code) only surfaces the session error on streams that have an 'error' listener, matching the existing emitStreamErrorNT guard; grpc-js forceShutdown no longer produces unhandled errors. - test-http-should-emit-timeout-event*.ts: requests that already completed do not get a 'timeout' event (Node semantics), so the test now uses an incomplete request and destroys the socket after the assertion. - 25190.test.ts: drain the server's data so the socket can emit 'close'. - expectations: skip the common.PIPE http tests on Windows (named-pipe listen unsupported), the flood/teardown http2 tests that only fail on Windows runners, and test-http2-pipe (server-side flow control stalls under reader backpressure when the response ended early; needs a native fix).
… close, net.Socket-based connection sockets, highWaterMark plumbing, HPE_PAUSED_H2_UPGRADE, relaxed header validation (client half), more expose-internals shim entries
… idle timer under kTimeout with write-progress suppression, respondWithFD bypasses the user-facing writable, strictSingleValueFields, deferred stream destroy when the request body is still buffered
…p-keep-alive-drop-requests to v26.3.0
…write-file as failing on Windows Both pass on POSIX; on Windows the file-pipe into the request stream does not complete and the session timeout fires during a large respondWithFD transfer. Tracked as Windows follow-ups.
…eHeaders option, handle.close callback contract A response that finishes before the request body has arrived no longer cuts the request off: remaining body bytes and trailers keep flowing and 'end' fires at real message completion (dumping only discards data). createServer's uniqueHeaders option joins listed headers on one line, and net handles pass a completion callback to close() like Node's handle contract.
It made requests on terminal paths (rejected smuggled bodies, empty optimized requests) wait for a message completion that never comes and trips a native assertion; restore the previous end-of-response behavior and the raw-headers expectations entry until a refined version lands.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Raises
node:http,node:https, andnode:http2compatibility — measured by running Node v26.3.0's owntest/parallel+test/sequentialhttp/https/http2 suites unmodified under Bun — from ~77% to ~93%, and syncs the vendored copies of those suites to v26.3.0.(Counts are upstream Node v26.3.0 test files run with the CI runner config, exit 0 = pass, Linux x64 debug builds; three of the remaining failures pass standalone and only time out under parallel debug load. The failing remainder is listed in
test/expectations.txt.)Server (node:http / node:https)
headersTimeout/requestTimeoutenforcement with Node'sconnectionsCheckingIntervalsweep and raw408reply;keepAliveTimeoutcloses idle keep-alive connections (0= no timeout);server.setTimeout/res.setTimeout/req.setTimeoutarm real per-socket timers, on TLS too.'connection'/'secureConnection'at accept/handshake time,'close'emitted whenever the TCP connection closes,closeIdleConnections/closeAllConnectionscounting, socket-error abort, and connection sockets are now realnet.Socketinstances with Node'ssocket.parsersurface (incoming,free(), kOnTimeout slot, freed before'upgrade'/'connect').clientErrorcontract (error reaches the client,bytesParsed/rawPacket, specificHPE_*codes incl.HPE_PAUSED_H2_UPGRADEfor an HTTP/2 preface, premature-EOF, chunked+Content-Length, bare CR, oversized chunk extensions with413/431replies).res.socket === null, ordered flush, bounded by read backpressure),maxRequestsPerSocket(503+'dropRequest'), half-close handling.'end'after handoff), incoming/outgoing trailers.Bun.servekeeps its lenient parser and fast paths unchanged.insecureHTTPParser/maxHeaderSize,createServer({ highWaterMark })plumbed to req/res, httpspfx/minVersion/maxVersion/ciphers/ALPN properties,req.socket.servername/authorized/authorizationError, relaxed (httpValidation) header validation on the client side, plus client/agent fixes (Node-exact messages, domain binding, parser reentrancy, abort/half-open lifecycle).node:http2
maxSessionMemory,maxSessionInvalidFrames, PING/SETTINGS-ACK floods).customSettings/remoteCustomSettings,enableConnectProtocol,strictSingleValueFields), Writable parity (write completion on flush,'drain',writableLength,bufferSize), session idle timer underkTimeoutwith write-progress suppression,respondWithFile/respondWithFDfd ownership and delivery, AsyncLocalStorage context on client streams, request queueing before connect, per-requestAbortSignal,performServerHandshake, allowHTTP1 fallback headers, Node-exact error wording.Tests
test/expectations.txtnow lists only the genuinely-failing remainder (65 entries removed in total across the PR — including the oldtest-stream-pipeline.jsskip and thetest-http2-pipe.jsflake, both fixed here — and 38 added for newly-vendored not-yet-passing tests).--expose-internalsharness shim gainedinternal/http,internal/options, andinternal/streams/stateentries so more upstream tests run unmodified.Verified
test/js/node/http/,test/js/node/http2/(incl. grpc-js),test/js/node/net/,test/js/node/tls/(per-file),test/js/bun/http/serve.test.ts(unchanged vs main).Pre-existing issues found while testing (not addressed here)
SSLWrapper/UpgradedDuplexteardown (UpgradedDuplex::on_closedrops the wrapper whilehandle_trafficframes still reference it). Reproduces on unmodified main via a single-processbun test test/js/node/tls/run; the fix belongs inUpgradedDuplex.rs(defer the wrapper drop likeWindowsNamedPipe.rs).test/js/node/tls/renegotiation.test.ts("renegotiation limit over a duplex socket") fails identically on released Bun in this environment.Remaining known gaps (tracked in
test/expectations.txt)Mostly tests that exercise Node-internal machinery that has no Bun equivalent (
internalBinding('http2')monkey-patching, V8%natives,TimersListinspection, async_hooks resource events, nghttp2-exact frame counts/padding), plus a handful of behavior gaps (HTTP over user-supplied generic streams, request dump/unconsume semantics, https server keylog/handshakeTimeout/ticket-key callbacks, max-header-size boundary accounting).