Socket.io: Middleware(.use) does not emit connect when using a custom namespace

Created on 11 Oct 2017  ·  12Comments  ·  Source: socketio/socket.io

You want to:

  • [x] report a bug
  • [ ] request a feature

Current behaviour

When using a custom namespace with a middleware the server gets a 'connection' event, but the client does not receive 'connect' event.

This works:

io.use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

This does not work:

// Following works, but client does not receive 'connect' or 'connection':
io.of('/admin').use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

Sitenotes

Also very strange: If i do the following code then also the default-namespace does not emit any 'connect' event even tho the middleware from /admin is not running.

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

io.of('/admin').use((socket, next) => {
   console.log('middleware running...');
   next();
}).on('connection', socket => {
  console.log('client connected');
});

To fix this i have to add .use((socket, next) => { next(); }) to default namespace. But still /admin does not emit 'connect'.

Steps to reproduce (if the current behaviour is a bug)

Please see above

Expected behaviour

On connection, client should receive 'connect'

Setup

  • OS: macOS Sierra 10.12.6
  • browser: Chrome
  • Node: v8.2.1
  • NPM: 5.4.2
  • socket.io version: 2.0.3
bug

Most helpful comment

@JanisRubens Thanks for the detailed report :+1: , I was eventually able to reproduce. Fixed by https://github.com/socketio/socket.io/pull/3197

All 12 comments

Hi! How are you initializing the client? The following seems to work for me:

io.use((socket, next) => {
   console.log('(default) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(default) client connected');
});

// Following works, but client does not receive 'connect' or 'connection':
io.of('/admin').use((socket, next) => {
   console.log('(admin) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(admin) client connected');
});

// client
const socket = require('socket.io-client')('http://localhost:3000/admin');

socket.on('connect', onConnect);

function onConnect(){
  console.log('connect ' + socket.id);
}

Output (fiddle):

server listening on port 3000
(default) middleware running...
(default) client connected
(admin) middleware running...
(admin) client connected

No it is not working for me. Full code, working example:

Server:

let express = require('express'),
    app = new express(),
    server = app.listen(3005, 'localhost'),
    io = require('socket.io')(server)
;

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

io.of('/admin')
  .use((socket, next) => {
    console.log('middleware running...');
    next();
  })
  .on('connection', socket => {
    console.log('admin connected');
  })
;

Client:

$(function () {
    let socket;

    $('#btn-connect').click(() => {
        console.log('Connecting ...');

        socket = io('http://localhost:3005');

        socket.on('connect', () => {
            console.log(`Connected to ${url} with id: ${socket.id}`);
        });

        socket.on('disconnect', reason => {
            console.log(`Disconnected. Reason: ${reason}`);
        });
    });

    $('#btn-connect-admin').click(() => {
        console.log('Connecting to admin ...');

        socket = io('http://localhost:3005/admin');

        socket.on('connect', () => {
            console.log(`Connected to ${url} with id: ${socket.id}`);
        });

        socket.on('disconnect', reason => {
            console.log(`Disconnected. Reason: ${reason}`);
        });
    });
});

If i remove the middleware i can connect to both. If i add the middleware to admin only, i get no connect event on default namespace nor /admin.

Server shows everything correctly:

  • client connected
  • middleware running...
  • admin connected

Nothing? :(

@MickL Any updates on this?
Ran into the same issue as well.
Not sure if you spotted this. The only connection issue is with root namespace and if you add a middleware also for the root path, it will be able to connect to it as well. ( this can be a quick fix tbh )

It comes down to following scenarios:

If namespace A('/)' and B('/otherPath') has no middleware it connects to both fine;
If namespace A has no middleware and B has. It connects to A on server side, but client sides 'connect' event listener never gets called, B namespace connects fine;
If namespace A and B both has middleware it can connect to both;

No i used a workaround. Instead of:

io.of('/admin')
  .use((socket, next) => {
    if(tokenValid()) {
       next();
    } else {
      next(new Error('Authentication error'));
    }
  })
  .on('connection', socket => {
    console.log('admin connected');
  })
;

I wrote:

io.of('/admin')
  .on('connection', socket => {
    if(!tokenValid()) {
       socket.disconnect();
    }

    console.log('admin connected');
  })
;

I spent a lot on this and it seems like the client does connect to the server but the client does not get the connection event.

I guess this can work. But it's a shame that we can't use middleware properly for its intended use.

@darrachequesne The example you provided and tested on is not as per reported issue.

You need to remove the middleware from the default namespace and then try to connect.

Like this:

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

io.of('/admin').use((socket, next) => {
   console.log('(admin) middleware running...');
   next();
}).on('connection', socket => {
  console.log('(admin) client connected');
});

// client
const socket = require('socket.io-client')('http://localhost:3000/');
const socket_two = require('socket.io-client')('http://localhost:3000/admin');
//wont trigger
socket.on('connect', onConnect);
//will trigger
socket_two.on('connect', onConnect);

function onConnect(){
  console.log('connect ' + socket.id);
}

Now it should fail.
See the cases when it works/does not work above.

Cheers.

@JanisRubens Thanks for the detailed report :+1: , I was eventually able to reproduce. Fixed by https://github.com/socketio/socket.io/pull/3197

I am still facing this!
Before creating namespace client receive events but after adding namespace and using middleware, client is not receiving any event however the frames was showing on the chrome.

+1

@adeelhussain @ElioTohm which version are you using? Are you able to reproduce the case with the fiddle?

using socketio v2.1.1 and socket.io-redis v5.2.0
i will try to reproduce it with fiddle asap

Was this page helpful?
0 / 5 - 0 ratings