socket.io icon indicating copy to clipboard operation
socket.io copied to clipboard

use() middleware is not triggered

Open SStoliarchuk opened this issue 3 years ago • 3 comments

Describe the bug of(/./).use() middleware is not triggered ~when using eiows.Server~ apparently also if we dont use the eiows.Server module it still shows the same behavior

To Reproduce We need three files, 1 server 2 client. Launch the server with nodemon server.js and open localhost:5656/1 and localhost:5656/2 Now both tabs should be connected to the socket io instance and in the terminal where the server was launched there would be printed

/admins slug __next__
/clients slug __next__

Put the terminal with nodemon on one side and the localhost:5656/2 tab on the other side with the devtools console open Save the file server.js with no changes and nodemon should restart the server, now in the console you will see only

/admins slug __next__

Now even if you reload the localhost:5656/2 page the console.log would still not work.

NOTE: Sometime it may work, so try to save again it takes some tries. I found that the best way to reproduce is to look at the devtools console and spam ctrl+s on the server.js file so that nodemon keeps restarting the server until the localhost:5656/2 devtools console throws an error saying ws connection cannot be made. When you see the error let the server start and the error should appear

Socket.IO server version: 4.4.0 Server

const express = require('express');
const http = require('http');
const { Server } = require("socket.io");
const eiows = require('eiows');

const app = express();
const server = http.createServer(app);

app.get('/1', (req, res) => {
  res.sendFile(__dirname + '/broken_socket.html');
});
app.get('/2', (req, res) => {
  res.sendFile(__dirname + '/broken_socket2.html');
});

const io = new Server(server, {
	path: '/socket',
	serveClient: false,
	wsEngine: eiows.Server,
});

io.of(/./).use(async (socket, next) => {
	socket.join(socket.handshake.auth.slug);
	io.of('/clients').to(socket.handshake.auth.slug).emit('6', {namespace: socket.nsp.name});
	console.log(socket.nsp.name, socket.handshake.auth.slug, '__next__');
	next();
});

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

Socket.IO client version: 4.4.0

Client 1

<script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous"></script>
<script>
	io('http://127.0.0.1:5656' + '/admins', {
		path: '/socket',
		transports: ['websocket'],
		auth: { slug: 'slug', token: 'token' },
	});
</script>

Client 2

<script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous"></script>
<script>
	io('http://127.0.0.1:5656' + '/clients', {
		path: '/socket',
		transports: ['websocket'],
		auth: { slug: 'slug', token: 'token' },
	});
</script>

Expected behavior The use() callback that contains the console.log should always be triggered but it is not

Additional context Please note that the error is caused by this line during the middleware: io.of('/clients').to(socket.handshake.auth.slug).emit('6', {namespace: socket.nsp.name}); we target /clients in this call, the same namespace that is not logged in the console.log

SStoliarchuk avatar Jan 04 '22 19:01 SStoliarchuk

I think this relates to: https://github.com/socketio/socket.io/issues/3960 https://github.com/socketio/socket.io/issues/4015 https://github.com/socketio/socket.io/issues/4164

~The current workaround that I have found it to emit on a setTimeout() with a 1 sec delay, less than that sometimes still breaks~

After reading better those issues I understand that this behavior is caused by the fact that when /admins connects first, it outputs to /clients which creates a namespace that has priority over the regex /./ match.

Would it be possible to still trigger the regex match? I think that would solve these 4 tickets

In the meanwhile the solution is to manually declare each namespace

SStoliarchuk avatar Jan 04 '22 19:01 SStoliarchuk

Hi. I'm adding a middleware on default the namespace. Unfortunately, after adding middleware, io instance stops firing events. Is this the same issue or unrelated? If I remove "use", everything works as expected.

Output:

io.of("/").use((socket, next) => {
  try {
    let data = verifyUserToken(socket);
    socket.data = data;
    next();
  } catch (error) {
    next(new Error("Socket middleware error"));
  }
});

yalcinozer avatar Mar 21 '22 19:03 yalcinozer

@yalcinozer I don't think this is related. Could you add a console.log() in the catch (error) {} block, to see if anything has gone wrong?

darrachequesne avatar Mar 21 '22 21:03 darrachequesne

Closed due to inactivity, please reopen if needed.

darrachequesne avatar Jun 19 '23 06:06 darrachequesne