Skip to content

WC to EXTERNAL WebSocket server requests fail with 400 BadRequest error, breaking Chat bots, DB connections and integrations #665

@FossPrime

Description

@FossPrime

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

  1. run this code an external containerd or baremetal server
  2. 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

Screenshots

FIXED and WORKING!!! WC Node.js connecting to a containerd Node.js in CodeSandbox:
{9343B83E-8BE7-475D-B720-C28D445E3534}

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions