Skip to content

fix(ext/node): emit "connect" event on http.Server for CONNECT requests#32599

Merged
bartlomieju merged 4 commits intomainfrom
fix/http-server-connect-event
Mar 12, 2026
Merged

fix(ext/node): emit "connect" event on http.Server for CONNECT requests#32599
bartlomieju merged 4 commits intomainfrom
fix/http-server-connect-event

Conversation

@bartlomieju
Copy link
Member

Summary

  • Deno's node:http Server polyfill never emitted the "connect" event for HTTP CONNECT method requests
  • This broke HTTP proxy libraries (e.g. proxy-chain, used by Crawlee/Playwright) that rely on this event to handle tunnel requests
  • Chrome launched with --proxy-server sends CONNECT requests to establish HTTPS tunnels — without the event, these were silently dropped, causing net::ERR_TIMED_OUT

Changes

  • Handle CONNECT method in ServerImpl._serve() by upgrading to a raw socket and emitting "connect" with (req, socket, head), matching Node.js behavior
  • Strip http:// prefix from CONNECT request URLs to return authority form (host:port) as Node.js does
  • Relax UpgradeStream status code check in http_next.rs to accept both 101 (WebSocket upgrade) and 200 (CONNECT tunnel)

Test plan

  • New spec test tests/specs/node/http_server_connect_event verifies full CONNECT tunnel flow (event emission, proxy tunnel establishment, data passthrough)
  • Existing upgrade/WebSocket tests continue to pass
  • Manual verification with Crawlee + Playwright

🤖 Generated with Claude Code

bartlomieju and others added 2 commits March 9, 2026 20:33
Fixes a crash where `testEnabled is not a function` is thrown during
bootstrap when internal stream code triggers debug logging before
`initializeDebugEnv()` has been called. This occurs when stdin is
unavailable, such as in compiled binaries run as Windows services
(via nssm) or processes detached with nohup/disown.

Initialize `testEnabled` and `debugImpls` with safe defaults
(`() => false` and empty object) so early calls to `debuglog()`
gracefully disable debug logging instead of crashing.

Closes #24208

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deno's node:http Server polyfill never emitted the "connect" event for
HTTP CONNECT method requests, causing HTTP proxy libraries (e.g.
proxy-chain, used by Crawlee) to silently drop tunnel requests. This
made Playwright/Crawlee's browser unable to navigate (net::ERR_TIMED_OUT)
since Chrome's CONNECT requests to the local proxy were never handled.

- Handle CONNECT method in ServerImpl._serve() by upgrading to a raw
  socket and emitting "connect" with (req, socket, head), matching
  Node.js behavior
- Strip "http://" prefix from CONNECT request URLs to return authority
  form (host:port) as Node.js does
- Relax UpgradeStream status code check to accept both 101 (WebSocket)
  and 200 (CONNECT tunnel)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bartlomieju
Copy link
Member Author

Related #26925

Copy link
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR correctly implements CONNECT request handling for http.Server, enabling HTTP proxy functionality. However, there's a minor Node.js API compatibility gap: the head parameter passed to the 'connect' event is hardcoded to an empty Buffer rather than containing any trailing data received after the CONNECT headers in the same TCP packet. While this doesn't break typical proxy use cases (data remains readable from the socket), it's a deviation from Node.js behavior that could affect proxies expecting pipelined data in the head buffer.

Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, pending the minor nit

bartlomieju and others added 2 commits March 12, 2026 18:00
Add a dedicated CONNECT upgrade path that sends the 200 response via
hyper, awaits the upgrade, and captures any trailing bytes (data
pipelined after the CONNECT request headers). These bytes are passed
as the `head` parameter to the "connect" event, matching Node.js
behavior.

The new UpgradeStream `ConsumeResponse` write state absorbs the
redundant HTTP response the application writes through the socket
(since hyper already sent 200), then switches to raw network mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	ext/http/http_next.rs
#	ext/node/polyfills/http.ts
@bartlomieju bartlomieju merged commit 1ea5ff0 into main Mar 12, 2026
112 checks passed
@bartlomieju bartlomieju deleted the fix/http-server-connect-event branch March 12, 2026 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants