socketio / socket.io

Realtime application framework (Node.JS server)
https://socket.io
MIT License
61.2k stars 10.11k forks source link

[Browser] Doesn't switch to polling when WebSocket is undefined. #5084

Closed hassansin closed 3 weeks ago

hassansin commented 1 year ago

I have set my transports to use WebSocket first and then fallback to polling e.g. transports: ["websocket", "polling"].

To test if the fallback transport really works, I used TamperMonkey browser extension to disable Websocket by setting WebSocket = void 0.

Instead of switching to polling, I keep getting connect_error with the message timeout from websocket transport.

Tried to investigate and it looks like transport switching only works if createTransport method throws here:

https://github.com/socketio/engine.io-client/blob/fa479164251dd1f283dd163143b546582161339a/lib/socket.ts#L467-L474

But the method always returns a transport wrapper class, even when WebSocket is not defined.

To Reproduce

Engine.IO server version: 6.5.2

Server

const engine = require("engine.io");
const server = engine.listen(3000, {
  transports: ["polling", "websocket"]
});

server.on("connection", (socket) => {
  console.log("connection");

  socket.on("message", (data) => {
    console.log("data", data);
  });

  socket.on("close", () => {
    console.log("close");
  });
});

Engine.IO client version: 6.5.2

Client

const socket = require("engine.io-client")("ws://localhost:3000", {
transports: ["websocket", "polling"]
});

socket.on("open", () => {
  console.log("open");

  socket.on("message", (data) => {
    console.log("data", data);
  });

  socket.on("close", () => {
    console.log("close");
  });
});

Expected behavior

Should be able to fallback to polling transport when WebSocket transport is disabled on the browser.

Platform:

Additional context Add any other context about the problem here.

darrachequesne commented 3 weeks ago

For future readers:

The tryAllTransports option let the client test all transports instead of just the first one:

import { io } from "socket.io-client";

const socket = io({
  tryAllTransports: true
});

Reference: https://socket.io/docs/v4/client-options/#transports

Implemented in https://github.com/socketio/engine.io-client/commit/579b243e89ac7dc58233f9844ef70817364ecf52, included in engine.io-client@6.6.0 and socket.io-client@4.8.0.