Dynamic Namespaces Socket.IO

javascript, node.js, socket.io

Solution

Socket.IO supports 'rooms' (https://github.com/LearnBoost/socket.io/wiki/Rooms), you can use it instead of namespaces. Also when you need dynamic in routes (and you using express in your app) - best way is to use use route-engine from express box.

- Best way to do dynamic routing with Express.js (node.js)

- Using routes in Express-js

- http://expressjs.com/api.html#app.routes

- http://shtylman.com/post/expressjs-re-routing/

- http://jordanhoff.com/post/22602013678/dynamic-express-routing

However, if you still think that you need dynamic in namespaces in socket.io, here is small example how it can be implemented:

User-side:

var connect = function (ns) {
    return io.connect(ns, {
       query: 'ns='+ns,
       resource: "socket.io"
    });
}

var socket = connect('/user/12');

Server-side:

var url = require('url');
  , ev = new events.EventEmitter()

// <ns name>: <ns regexp>
var routes = {
  // /user/:id
  'user': '^\\/user\\/(\\d+)$',

  // /:something/:id
  'default': '^\\/(\\\w+)\\/(\\d+)$'
};

// global entry point for new connections
io.sockets.on('connection', function (socket) {
  // extract namespace from connected url query param 'ns'
  var ns = url.parse(socket.handshake.url, true).query.ns;
  console.log('connected ns: '+ns)

  //
  for (var k in routes) {
    var routeName = k;
    var routeRegexp = new RegExp(routes[k]);

    // if connected ns matched with route regexp
    if (ns.match(routeRegexp)) {
      console.log('matched: '+routeName)

      // create new namespace (or use previously created)
      io.of(ns).on('connection', function (socket) {
        // fire event when socket connecting
        ev.emit('socket.connection route.'+routeName, socket);

        // @todo: add more if needed
        // on('message') -> ev.emit(...)
      });

      break;
    }
  }

  // when nothing matched
  // ...
});

// event when socket connected in 'user' namespace
ev.on('socket.connection route.user', function () {
  console.log('route[user] connecting..');
});

// event when socket connected in 'default' namespace
ev.on('socket.connection route.default', function () {
  console.log('route[default] connecting..');
});

I hope this will help you!

Problem

How can I use dynamic namespaces in socket.io. I'm looking in the (poor) documentation, and it says that namespaces must be used like this: `io.of('/news')` `io.of('/akfda')` To use a namespace you do `io.of("/namespace")`. Do I need to register every single namespace in the server? Maybe I want a namespace for dynamic content. How can I do something like : `io.of('/:somethign/:id')`

Original source

Related problems