Replace http.request() with raw TCP/TLS sockets for CONNECT tunneling#663
Draft
jancurn wants to merge 2 commits into
Draft
Replace http.request() with raw TCP/TLS sockets for CONNECT tunneling#663jancurn wants to merge 2 commits into
jancurn wants to merge 2 commits into
Conversation
Two narrowly-scoped fixes that knock out concrete failure categories in the Bun e2e suite without touching Node behavior: 1. `count_target_bytes` now also accumulates bytes via passive 'data' listeners on the target socket and via a 'pipe'/'unpipe'-tracked listener on whatever's piped into it. Node continues to win on its own `socket.bytesRead`/`bytesWritten` counters (they're always at least as high as the manual tally, so `Math.max` keeps them). Bun 1.3 reports 0 on http client sockets — the manual counters now carry it. 2. Regenerated `test/e2e/ssl.crt` / `ssl.key` with a 100-year validity. The previous cert expired 2018-11-10; Node accepted it because the tests pass `rejectUnauthorized: false`, but Bun rejects expired certs strictly on the WS path and four `https-stress` / WS tests failed with "certificate has expired".
…as-request in server Inspired by #649. Two changes that let proxy-chain itself run under Bun when used as a library, independent of what the test harness can prove: 1. `src/chain.ts` no longer goes through `http.request().on('connect')` to reach the upstream proxy. Bun 1.3 implements http.request on top of fetch and (a) rejects RFC 7230 authority-form paths like `:443` with "fetch() URL is invalid", (b) swallows the 407/590-class upstream responses. We now open a raw `net` or `tls` socket, send the CONNECT line ourselves, parse the response header buffer, and hand the remaining bytes back via `socket.unshift`. `rawHeaders` is preserved on the synthetic IncomingMessage so `tunnelConnectResponded` subscribers (the anonymizeProxy listener test) keep working. 2. `Server.onRequest` falls back to `onConnect` when `request.method === 'CONNECT'`. Bun delivers CONNECT through the generic 'request' event for some client shapes; Node ignores this branch because it always uses the dedicated 'connect' event.
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.
Summary
Refactors the upstream proxy CONNECT tunnel implementation to use raw TCP/TLS sockets instead of
http.request()with the 'connect' event. This change improves compatibility with runtimes like Bun 1.3 that have limitations with their HTTP client implementation.Key Changes
Chain handler refactoring: Replaced
http.request()/https.request()with directnet.createConnection()andtls.connect()callsByte counting improvements: Enhanced
countTargetBytes()utility to handle runtimes where socket-level byte counters are unreliablebytesRead/bytesWrittenreport 0Server request routing: Added explicit routing of CONNECT requests through
onConnect()in the 'request' event handlerSSL certificate regeneration: Updated test SSL certificate and key to use modern PKCS#8 format
Implementation Details
The raw socket approach sidesteps two Bun 1.3 quirks:
:443with "fetch() URL is invalid"Manual byte counting uses passive listeners with zero overhead on Node.js (socket counters always win) while providing the only reliable source of truth on Bun 1.3
Maintains full backward compatibility with existing behavior on Node.js while improving cross-runtime support
https://claude.ai/code/session_01Vn16UCyisJSwEaAoHLSNX6