Compare commits

...

9 Commits

Author SHA1 Message Date
Roman Shtylman
213577204a Merge branch 'dynamic-namespaces' of https://github.com/markitx/socket.io into dynamic-namespace
Conflicts:
	lib/client.js
	test/socket.io.js
2015-02-04 18:17:49 -08:00
Dylan Lingelbach
dd72676c25 Make name more descriptive 2015-02-04 13:43:21 -06:00
Dylan Lingelbach
3bf7be73a0 Style cleanup 2015-02-04 13:40:40 -06:00
Dylan Lingelbach
0360553c99 Merge branch 'master' into dynamic-namespaces 2015-02-04 13:10:40 -06:00
Dylan Lingelbach
de5cbdb833 Improve tests 2015-02-04 12:33:18 -06:00
Dylan Lingelbach
0ce0ce1dbc Merge pull request #1 from markitx/dynamic-namespaces
Dynamic namespaces
2015-01-09 11:56:51 -06:00
Dylan Lingelbach
cc7ce79251 Ensure server sends connect message 2014-12-19 15:32:20 -06:00
Dylan Lingelbach
1b77c27f7b Fix test 2014-12-19 15:27:08 -06:00
Dylan Lingelbach
1f8bb8a0ec Support dynamic namespaces 2014-12-19 13:22:41 -06:00
3 changed files with 152 additions and 18 deletions

View File

@@ -59,26 +59,40 @@ Client.prototype.setup = function(){
*/
Client.prototype.connect = function(name){
debug('connecting to namespace %s', name);
if (!this.server.nsps[name]) {
this.packet({ type: parser.ERROR, nsp: name, data : 'Invalid namespace'}, false, false, true);
return;
}
var nsp = this.server.of(name);
if ('/' != name && !this.nsps['/']) {
this.connectBuffer.push(name);
return;
}
var self = this;
var socket = nsp.add(this, function(){
self.sockets.push(socket);
self.nsps[nsp.name] = socket;
debug('connecting to namespace %s', name);
if ('/' == nsp.name && self.connectBuffer.length > 0) {
self.connectBuffer.forEach(self.connect, self);
self.connectBuffer = [];
function connectNamespace() {
var nsp = self.server.of(name);
if ('/' != name && !self.nsps['/']) {
self.connectBuffer.push(name);
return;
}
var socket = nsp.add(self, function(){
self.sockets.push(socket);
self.nsps[nsp.name] = socket;
if ('/' == nsp.name && self.connectBuffer.length > 0) {
self.connectBuffer.forEach(self.connect, self);
self.connectBuffer = [];
}
});
}
if (self.server.nsps[name]) {
// Namespace already created, connect
connectNamespace();
return;
}
self.server.checkNamespace(name, function(allow) {
if (allow) {
connectNamespace();
return
}
self.packet({ type: parser.ERROR, nsp: name, data : 'Invalid namespace'});
});
};

View File

@@ -43,6 +43,7 @@ function Server(srv, opts){
}
opts = opts || {};
this.nsps = {};
this.nspValidators = [];
this.path(opts.path || '/socket.io');
this.serveClient(false !== opts.serveClient);
this.adapter(opts.adapter || Adapter);
@@ -137,6 +138,53 @@ Server.prototype.set = function(key, val){
return this;
};
/**
* Sets up server middleware to validate incoming namespaces not already created on the server.
*
* @return {Server} self
* @api public
*/
Server.prototype.useNamespaceValidator = function(fn){
this.nspValidators.push(fn);
return this;
};
/**
* Executes the middleware for an incoming namespace not already created on the server.
*
* @param name of incomming namespace
* @param {Function} last fn call in the middleware
* @api private
*/
Server.prototype.checkNamespace = function(name, fn){
var fns = this.nspValidators.slice(0);
if (!fns.length) return fn(false);
var namespaceAllowed = false; // Deny unknown namespaces by default
function run(i){
fns[i](name, function(err, allow){
// upon error, short-circuit
if (err) return fn(false);
// if one piece of middleware explicitly denies namespace, short-circuit
if (allow === false) return fn(false);
namespaceAllowed = namespaceAllowed || allow === true;
// if no middleware left, summon callback
if (!fns[i + 1]) return fn(namespaceAllowed);
// go on to next
run(i + 1);
});
}
run(0);
};
/**
* Sets the client serving path.
*

View File

@@ -597,7 +597,7 @@ describe('socket.io', function(){
});
});
});
it('should not reuse same-namespace connections', function(done){
var srv = http();
var sio = io(srv);
@@ -730,6 +730,78 @@ describe('socket.io', function(){
});
}
});
it('should allow connections to dynamic namespaces', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var namespace = '/dynamic';
var dynamic = client(srv,namespace);
sio.useNamespaceValidator(function(nsp, next) {
expect(nsp).to.be(namespace);
next(null, true);
});
dynamic.on('error', function(err) {
expect().fail();
});
dynamic.on('connect', function() {
expect(sio.nsps[namespace]).to.be.a(Namespace);
expect(sio.nsps[namespace].sockets.length).to.be(1);
done();
});
});
});
it('should not allow connections to dynamic namespaces if not supported', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var namespace = '/dynamic';
sio.useNamespaceValidator(function(nsp, next) {
expect(nsp).to.be(namespace);
next(null, false);
});
sio.on('connect', function(socket) {
if (socket.nsp.name === namespace) {
expect().fail();
}
});
var dynamic = client(srv,namespace);
dynamic.on('connect', function(){
expect().fail();
});
dynamic.on('error', function(err) {
expect(err).to.be("Invalid namespace");
done();
});
});
});
it('should not allow connections to dynamic namespaces if there is an error', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var namespace = '/dynamic';
sio.useNamespaceValidator(function(nsp, next) {
expect(nsp).to.be(namespace);
next(new Error(), true);
});
sio.on('connect', function(socket) {
if (socket.nsp.name === namespace) {
expect().fail();
}
});
var dynamic = client(srv,namespace);
dynamic.on('connect', function(){
expect().fail();
});
dynamic.on('error', function(err) {
expect(err).to.be("Invalid namespace");
done();
});
});
});
});
describe('socket', function(){