diff --git a/lib/index.js b/lib/index.js index 3cae6c10de..5287e4ead0 100644 --- a/lib/index.js +++ b/lib/index.js @@ -54,7 +54,7 @@ function Server(srv, opts){ this.parser = opts.parser || parser; this.encoder = new this.parser.Encoder(); this.adapter(opts.adapter || Adapter); - this.origins(opts.origins || []); + this.origins(opts.origins || '*:*'); this.sockets = this.of('/'); if (srv) this.attach(srv, opts); } @@ -67,18 +67,31 @@ function Server(srv, opts){ */ Server.prototype.checkRequest = function(req, fn) { - const origin = req.headers.origin; + var origin = req.headers.origin || req.headers.referer; - if (typeof this._origins === 'function') { - return this._origins(origin, fn); - } + // file:// URLs produce a null Origin which can't be authorized via echo-back + if ('null' == origin || null == origin) origin = '*'; + if (!!origin && typeof(this._origins) == 'function') return this._origins(origin, fn); + if (this._origins.indexOf('*:*') !== -1) return fn(null, true); if (origin) { - fn(null, this._origins.includes(origin)); - } else { - const noOriginIsValid = this._origins.length === 0; - fn(null, noOriginIsValid); + try { + var parts = url.parse(origin); + var defaultPort = 'https:' == parts.protocol ? 443 : 80; + parts.port = parts.port != null + ? parts.port + : defaultPort; + var ok = + ~this._origins.indexOf(parts.protocol + '//' + parts.hostname + ':' + parts.port) || + ~this._origins.indexOf(parts.hostname + ':' + parts.port) || + ~this._origins.indexOf(parts.hostname + ':*') || + ~this._origins.indexOf('*:' + parts.port); + debug('origin %s is %svalid', origin, !!ok ? '' : 'not '); + return fn(null, !!ok); + } catch (ex) { + } } + fn(null, false); }; /** @@ -224,7 +237,7 @@ Server.prototype.adapter = function(v){ Server.prototype.origins = function(v){ if (!arguments.length) return this._origins; - this._origins = typeof v === 'string' ? [v] : v; + this._origins = v; return this; }; diff --git a/test/socket.io.js b/test/socket.io.js index 7252bb78e7..6cc085b798 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -73,7 +73,7 @@ describe('socket.io', function(){ it('should be able to set origins to engine.io', function() { var srv = io(http()); srv.set('origins', 'http://hostname.com:*'); - expect(srv.origins()).to.eql(['http://hostname.com:*']); + expect(srv.origins()).to.be('http://hostname.com:*'); }); it('should be able to set authorization and send error packet', function(done) { @@ -262,6 +262,17 @@ describe('socket.io', function(){ }); }); + it('should allow request when origin defined an the same is specified', function(done) { + var sockets = io({ origins: 'http://foo.example:*' }).listen('54015'); + request.get('http://localhost:54015/socket.io/default/') + .set('origin', 'http://foo.example') + .query({ transport: 'polling' }) + .end(function (err, res) { + expect(res.status).to.be(200); + done(); + }); + }); + it('should allow request when origin defined as function and same is supplied', function(done) { var sockets = io({ origins: function(origin,callback){ if (origin == 'http://foo.example') { @@ -296,7 +307,7 @@ describe('socket.io', function(){ it('should allow request when origin defined as function and no origin is supplied', function(done) { var sockets = io({ origins: function(origin,callback){ - if (origin === undefined) { + if (origin == '*') { return callback(null, true); } return callback(null, false); @@ -309,6 +320,17 @@ describe('socket.io', function(){ }); }); + it('should default to port 443 when protocol is https', function(done) { + var sockets = io({ origins: 'https://foo.example:443' }).listen('54036'); + request.get('http://localhost:54036/socket.io/default/') + .set('origin', 'https://foo.example') + .query({ transport: 'polling' }) + .end(function (err, res) { + expect(res.status).to.be(200); + done(); + }); + }); + it('should allow request if custom function in opts.allowRequest returns true', function(done){ var sockets = io(http().listen(54022), { allowRequest: function (req, callback) { return callback(null, true); @@ -345,17 +367,6 @@ describe('socket.io', function(){ done(); }); }); - - it('should disallow any origin by default', (done) => { - io().listen('54025'); - request.get('http://localhost:54025/socket.io/default/') - .set('origin', 'https://foo.example') - .query({ transport: 'polling' }) - .end((err, res) => { - expect(res.status).to.be(403); - done(); - }); - }); }); describe('close', function(){