Register the connection listener explicitly, so re-emitted sockets are handled - #4
Closed
gkurt wants to merge 1 commit into
Closed
Register the connection listener explicitly, so re-emitted sockets are handled#4gkurt wants to merge 1 commit into
gkurt wants to merge 1 commit into
Conversation
The two forms are equivalent in Node, where net.Server's constructor argument
is registered as a 'connection' listener. Only the explicit form is portable:
runtimes that handle the constructor callback internally never dispatch to it
from server.emit('connection', socket), which is how a proxy re-injects a
tunnelled socket after CONNECT.
Adds a test covering that re-injection path, which mockttp depends on and
which was previously only implicit.
gkurt
force-pushed
the
explicit-connection-listener
branch
from
August 31, 2026 16:15
0df4487 to
d36c4b9
Compare
|
|
Author
|
@pimterry sorry for the PR. I intended to review this before opening a PR, but Claude opened it anyway. This indeed needs to be fixed in Bun, and seems like it's already fixed on main. I am so sorry for this. Closing. |
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.
Servercurrently passes its connection handler tonet.Server's constructor:In Node this is exactly equivalent to registering a
'connection'listener — theconstructor argument is added with
this.on('connection', …)— so re-emitting asocket onto the server dispatches to it. That behaviour is load-bearing for
httpolyglot's main consumer: mockttp re-injects the tunnelled socket after
CONNECTwith
server.emit('connection', socket), so that a tunnelled connection gets sniffedand routed exactly like a direct one.
The equivalence doesn't hold on every runtime. Bun handles the constructor callback
internally rather than registering it as a listener:
listeners('connection')is empty,and
emit('connection', socket)never reachesconnectionListener. Genuine inboundconnections still work, so a polyglot server looks healthy right up until something
re-injects a socket — at which point the socket is silently never read and the peer
hangs with no error on either side. (Filed upstream at oven-sh/bun#41060.)
This switches to the explicit form:
which is a no-op on Node — same registration, same ordering, nothing can attach a
listener between
super()and the.on()call — and makes the re-injection contracthold on runtimes that treat the constructor argument specially.
Tests
Adds
test/reinjected-connection.spec.ts, which stands up a plainnet.Serverin therole of a proxy's
CONNECThandler, hands the accepted socket back to the polyglotserver via
emit('connection', …), and asserts the request is routed to the HTTPlistener.
The new test passes on Node either way — it can't fail there, since the two forms are
equivalent. Its value is that it pins a contract that mockttp depends on and that is
currently only implicit.
One note if you reproduce the Bun column:
bun x mocharuns mocha under Node (thebinary's shebang wins), so the test appears to pass unpatched.
bun --bun x mochaiswhat actually runs it under Bun.
Notes
I'm not asking you to support Bun — the ALPN gap below means httpolyglot's TLS path
can't fully work there yet regardless. This is narrower than that: the constructor
form's equivalence to
.on('connection')is a Node implementation detail, and theexplicit form costs nothing to prefer.