From db36d031bc8f821544973598a49a248eef02676c Mon Sep 17 00:00:00 2001 From: Tony Kovanen Date: Wed, 9 Apr 2014 22:26:10 +0300 Subject: [PATCH 1/3] Added support for giving a function to engine.io to decide whether a request should be allowed or not when verifying. This is used by socket.io to check for allowed origins. --- lib/server.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/server.js b/lib/server.js index fe75d5d5..28cf42a1 100644 --- a/lib/server.js +++ b/lib/server.js @@ -38,6 +38,7 @@ function Server(opts){ this.maxHttpBufferSize = opts.maxHttpBufferSize || 10E7; this.transports = opts.transports || Object.keys(transports); this.allowUpgrades = false !== opts.allowUpgrades; + this.allowRequest = opts.allowRequest; this.cookie = false !== opts.cookie ? (opts.cookie || 'io') : false; // initialize websocket server @@ -117,8 +118,8 @@ Server.prototype.verify = function(req, upgrade){ } } else { // handshake is GET only - return 'GET' == req.method || - Server.errors.BAD_HANDSHAKE_METHOD; + if ('GET' != req.method) return Server.errors.BAD_HANDSHAKE_METHOD; + return !this.allowRequest || this.allowRequest(req); } return true; From 802f1300802f35f4112c015cb19441fc2fe17d2f Mon Sep 17 00:00:00 2001 From: Tony Kovanen Date: Thu, 10 Apr 2014 21:03:08 +0300 Subject: [PATCH 2/3] Made the request verification process async --- lib/server.js | 59 +++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/lib/server.js b/lib/server.js index 28cf42a1..6209d681 100644 --- a/lib/server.js +++ b/lib/server.js @@ -99,30 +99,31 @@ Server.prototype.upgrades = function(transport){ * @api private */ -Server.prototype.verify = function(req, upgrade){ +Server.prototype.verify = function(req, upgrade, fn){ // transport check var transport = req._query.transport; if (!~this.transports.indexOf(transport)) { debug('unknown transport "%s"', transport); - return Server.errors.UNKNOWN_TRANSPORT; + return fn(Server.errors.UNKNOWN_TRANSPORT, false); } // sid check var sid = req._query.sid; if (sid) { if (!this.clients.hasOwnProperty(sid)) - return Server.errors.UNKNOWN_SID; + return fn(Server.errors.UNKNOWN_SID, false); if (!upgrade && this.clients[sid].transport.name !== transport) { debug('bad request: unexpected transport without upgrade'); - return Server.errors.BAD_REQUEST; + return fn(Server.errors.BAD_REQUEST, false); } } else { // handshake is GET only - if ('GET' != req.method) return Server.errors.BAD_HANDSHAKE_METHOD; - return !this.allowRequest || this.allowRequest(req); + if ('GET' != req.method) return fn(Server.errors.BAD_HANDSHAKE_METHOD, false); + if (!this.allowRequest) return fn(null, true); + return this.allowRequest(req, fn); } - return true; + fn(null, true); }; /** @@ -165,20 +166,20 @@ Server.prototype.handleRequest = function(req, res){ this.prepare(req); req.res = res; - var code = this.verify(req, false); - if (code !== true) { - sendErrorMessage(res, code); - return this; - } + var self = this; + this.verify(req, false, function(err, success) { + if (!success) { + sendErrorMessage(res, err); + return; + } - if (req._query.sid) { - debug('setting new request for existing client'); - this.clients[req._query.sid].transport.onRequest(req); - } else { - this.handshake(req._query.transport, req); - } - - return this; + if (req._query.sid) { + debug('setting new request for existing client'); + self.clients[req._query.sid].transport.onRequest(req); + } else { + self.handshake(req._query.transport, req); + } + }); }; /** @@ -258,15 +259,17 @@ Server.prototype.handshake = function(transport, req){ Server.prototype.handleUpgrade = function(req, socket, head){ this.prepare(req); - if (this.verify(req, true) !== true) { - socket.end(); - return; - } - - // delegate to ws var self = this; - this.ws.handleUpgrade(req, socket, head, function(conn){ - self.onWebSocket(req, conn); + this.verify(req, true, function(err, success) { + if (!success) { + socket.end(); + return; + } + + // delegate to ws + self.ws.handleUpgrade(req, socket, head, function(conn){ + self.onWebSocket(req, conn); + }); }); }; From 5b7f0cffb134238b44d9247b9024c803865ede16 Mon Sep 17 00:00:00 2001 From: Tony Kovanen Date: Fri, 11 Apr 2014 01:23:42 +0300 Subject: [PATCH 3/3] Updated README to include allowRequest callback --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 5615da2d..3833dd4d 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,12 @@ to a single process. - `maxHttpBufferSize` (`Number`): how many bytes or characters a message can be when polling, before closing the session (to avoid DoS). Default value is `10E7`. + - `allowRequest` (`Function`): A function that receives a given handshake + or upgrade request as its first parameter, and can decide whether to + continue or not. The second argument is a function that needs to be + called with the decided information: `fn(err, success)`, where + `success` is a boolean value where false means that the request is + rejected, and err is an error code. - `transports` (` String`): transports to allow connections to (`['polling', 'websocket', 'flashsocket']`) - `allowUpgrades` (`Boolean`): whether to allow transport upgrades