-
Notifications
You must be signed in to change notification settings - Fork 269
Description
Describe the bug
Trying to connect to a WebSockets server from WebContainers causes a 400 Bad Request error. This happens even when connecting to remote Socket.io servers from within a WebContainer.
Connecting to WebSockets servers from the browser works normally, as long as CORS is configured. this issue is not about connections from the browser. This issue is exclusively about connecting from WebContainers to EXTERNAL WebSocket servers. No browser code at all is necessary to encounter this issue.
This affects:
- Chatbots connecting to external WebSocket servers
- Socket.io and Feathers api tests
- Connections to DBs from SB via a external WebSockets servers
- Access to WebSockets based live data APIs
- Dependencies and utilities that spawn a new node process to connect to your WS server
Link to the blitz that caused the error
Simplest socket.io example: https://stackblitz.com/edit/sb-ws-bug?file=vite.config.ts,ReadMe.md
Steps to reproduce
- run this code an external containerd or baremetal server
- run this code on SB but make SOCKET_URI in vite.config.ts point to the external server.
Expected behavior
All posted "Chatbot" messages will print to the console.
Actual Behavior
- Status code 400 'Bad Request' errors.
- WebContainers unable to connect to external WebSockets servers
Parity with Local
- I have run the project in my local machine and I could not reproduce the issue.
Screenshots
FIXED and WORKING!!! WC Node.js connecting to a containerd Node.js in CodeSandbox:

Platform
- OS: Linux
- Browser: Chrome
- Version: 100
Additional context
Suspicious line of code in file:///root/project/packages/browser-node/@node/_http_client.js
// If the user did not listen for the 'response' event, then they
// can't possibly read the data, so we ._dump() it into the void
// so that the socket doesn't hang there in a paused state.
if (req.aborted || !req.emit('response', res))
res._dump();
Upgrade requests seem to be getting handled as a normal response, and then disconnected.
Workarounds:
- It is possible to use the browser as a WebSockets relay
- Abomination: https://stackblitz.com/edit/nodemon-xyvji4?file=vite.config.ts
- This only works for basic socket.io apps. If you use a library on top of socket.io, you'll have to create custom glue code and won't have a way to make a general relay. As there is no public API for socke.io connect event spoofing, and to spoof it we need the original connect event that we can use to call dispatchEvent.
- connection upgrades might work if we set a dummy 'response' event listener on the upgrade request... This isn't possible to do with Socket.io, so it's not viable for most people, if it works.