Websocket connection error : Does not return a 101 changing protocal when using from different path

2.4k Views Asked by At

I am using easy-rtc with socket.io for multiuser experience in my metaverse project. We maintain the connection in socket.io using polling and web-socket. I am facing problem in web-socket connection when I am trying to give path to the socket.io.

Firstly, I am putting forward the code where I am not using any path. You can get the complete code from here. https://github.com/networked-aframe/networked-aframe/blob/master/server/easyrtc-server.js

Code without Path(1)

Code without Path(2)

Code without Path(3)

The web-socket connection request which I am getting from this code is giving me a 101 changing protocols as expected.

Web-socket connection Request (working Fine)

I am even getting the response for the web-socket request as connecting in the Postman.

Postman web-socket request

Now, My backend is working at localhost:3333/api/ . I am trying to change the path of socket.io in the client and server as shown in the images below. but I am not getting the 101 changing protocol response from web-socket connection request. This is the code after path change.

This is the client side code:setting socket URL path in client side

This is the backend code : Setting path for socket.io in backend

This is the response which I am getting when running the code after doing the path changes. Web-Socket not giving 101 changing protocols

When I am trying to hit the web-socket request in the postman also I am not getting any connection. One observation I have made is that in the request URL, it is not taking the localhost:3333/api/ path. (If this is the issue, suggest any work arounds for this.) Web-socket request in postman

Without getting the web-socket connection, the server is not efficient for communication.

Anyone suggest working solutions for this.

1

There are 1 best solutions below

2
On BEST ANSWER

I was able to reproduce it.

A working solution

The problem is in your server code. You are doing something like this:

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server, {path: '/api/socket.io'}) // here you are already attaching the socket.io server to the HTTP server
const socketServer = io.listen(server) // this line is not required!

The last line is not required. It should be used only with socket server istances not yet attached to any http server. In the previous line you are already importing the socket.io main function, calling it, attaching to the HTTP server.
Therefore, try removing the .listen call and you will receive the 101 changing protocol http status code again.

With the above proposed solution, you can listen on socket events directly using the io istance. Like this:

io.on('connection', (socket) => {
    console.log('a user connected');
});

Why it was working without the path?

Well, the first code snipped you provided should not work at all. From what I can see you were doing this:

const socketIo = require('socket.io')
socketIo.listen(webServer, {"log level": 1})

The above code can't work. The socketIo variable is an anonymous function. The listen method is not defined. Are you sure you have not initialized the module in a different way? Maybe are you using and old version of socket.io?

A better approach

Anyway, I suggest the new fresh, clean syntax socket.io documentation suggests;
Backend:

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, {path: '/api/socket.io'});

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
   console.log('a user connected');
});

server.listen(3000, () => {
    console.log('listening on *:3000');
});

Client (I'm using a CDN but you could rely to your server for the socket.io-client code):

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <script type="module">
      import { io } from "https://cdn.socket.io/4.4.1/socket.io.esm.min.js";
  
      const socket = io({path: "/api/socket.io"});
    </script>
  </body>
</html>

enter image description here