Skip to content

fix: support WebSocket upgrades in Vite dev server#3737

Open
bartlomieju wants to merge 2 commits intomainfrom
fix/websocket-upgrade-dev-server
Open

fix: support WebSocket upgrades in Vite dev server#3737
bartlomieju wants to merge 2 commits intomainfrom
fix/websocket-upgrade-dev-server

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

  • Fix WebSocket upgrade requests never reaching Fresh handlers in Vite dev mode (Fresh V2 Beta WebSocket upgrade request never reaches server behind vite development environment #3350)
  • Vite's Connect-based server fires upgrade events on the underlying http.Server rather than routing them through middleware, so Deno.upgradeWebSocket() was never called
  • Start a Deno.serve() on a random port alongside Vite and proxy upgrade requests to it via raw TCP socket forwarding, where Deno.upgradeWebSocket() works natively
  • Vite's own HMR WebSocket paths (/__vite_hmr, /__vite_ping) are excluded from proxying

Test plan

  • New test vite dev - websocket upgrade verifies echo via WebSocket in dev mode
  • Verify existing dev server tests still pass
  • Manual test with a real WebSocket-based app in dev mode

Fixes #3350

🤖 Generated with Claude Code

WebSocket upgrade requests never reached Fresh handlers in dev mode
because Vite's Connect-based server fires 'upgrade' events on the
underlying http.Server rather than routing them through middleware.

Fix by starting a Deno HTTP server on a random port alongside Vite
and proxying upgrade requests to it via raw TCP socket forwarding.
This allows Deno.upgradeWebSocket() to work natively.

Fixes #3350

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju force-pushed the fix/websocket-upgrade-dev-server branch from 8bc3c1c to 1ac26e1 Compare March 29, 2026 08:33
- Replace Buffer type with Uint8Array to fix CI type checking
- Add onError handler to Deno.serve to suppress broken pipe errors
- Add close event handlers on proxy sockets for clean teardown
- Wrap destroy calls in try/catch to prevent cascading errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju
Copy link
Copy Markdown
Member Author

The second Deno.serve() + TCP proxy approach here works but is heavier than ideal. The root cause is that Deno.upgradeWebSocket() doesn't work with requests from node:http upgrade events — filed denoland/deno#33220 to track fixing this at the Deno level.

Once that Deno issue is resolved, this workaround can be replaced with a simple upgrade event handler that calls the Fresh handler directly. Until then, this is the only viable approach.

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.

Fresh V2 Beta WebSocket upgrade request never reaches server behind vite development environment

1 participant