engine.io
Advanced tools
Comparing version 1.2.2 to 1.3.0
1.3.0 / 2014-06-13 | ||
================== | ||
* update example to use v1.2.2 | ||
* fixed newline parsing in jsonp | ||
* make require('engine.io')() return a new Server instance [defunctzombie] | ||
* add Server.attach method [defunctzombie] | ||
* fix GH-211, set CORS headers when sending error message [mokesmokes] | ||
1.2.2 / 2014-05-30 | ||
@@ -3,0 +12,0 @@ ================== |
module.exports = process.env.EIO_COV | ||
? require('./lib-cov') | ||
: require('./lib'); | ||
? require('./lib-cov/engine.io') | ||
: require('./lib/engine.io'); |
@@ -5,6 +5,29 @@ /** | ||
var http = require('http') | ||
, debug = require('debug')('engine:core'); | ||
var http = require('http'); | ||
/** | ||
* Invoking the library as a function delegates to attach if the first argument | ||
* is an `http.Server`. | ||
* | ||
* If there are no arguments or the first argument is an options object, then | ||
* a new Server instance is returned. | ||
* | ||
* @param {http.Server} server (if specified, will be attached to by the new Server instance) | ||
* @param {Object} options | ||
* @return {Server} engine server | ||
* @api public | ||
*/ | ||
exports = module.exports = function() { | ||
// backwards compatible use as `.attach` | ||
// if first argument is an http server | ||
if (arguments.length && arguments[0] instanceof http.Server) { | ||
return attach.apply(this, arguments); | ||
} | ||
// if first argument is not an http server, then just make a regular eio server | ||
return exports.Server.apply(null, arguments); | ||
}; | ||
/** | ||
* Protocol revision number. | ||
@@ -67,3 +90,5 @@ * | ||
exports.listen = function (port, options, fn) { | ||
exports.listen = listen; | ||
function listen(port, options, fn) { | ||
if ('function' == typeof options) { | ||
@@ -97,53 +122,8 @@ fn = options; | ||
exports.attach = function (server, options) { | ||
exports.attach = attach; | ||
function attach(server, options) { | ||
var engine = new exports.Server(options); | ||
var options = options || {}; | ||
var path = (options.path || '/engine.io').replace(/\/$/, ''); | ||
var destroyUpgrade = (options.destroyUpgrade !== undefined) ? options.destroyUpgrade : true; | ||
var destroyUpgradeTimeout = options.destroyUpgradeTimeout || 1000; | ||
// normalize path | ||
path += '/'; | ||
function check (req) { | ||
return path == req.url.substr(0, path.length); | ||
} | ||
// cache and clean up listeners | ||
var listeners = server.listeners('request').slice(0); | ||
server.removeAllListeners('request'); | ||
server.on('close', engine.close.bind(engine)); | ||
// add request handler | ||
server.on('request', function(req, res){ | ||
if (check(req)) { | ||
debug('intercepting request for path "%s"', path); | ||
engine.handleRequest(req, res); | ||
} else { | ||
for (var i = 0, l = listeners.length; i < l; i++) { | ||
listeners[i].call(server, req, res); | ||
} | ||
} | ||
}); | ||
if(~engine.transports.indexOf('websocket')) { | ||
server.on('upgrade', function (req, socket, head) { | ||
if (check(req)) { | ||
engine.handleUpgrade(req, socket, head); | ||
} else if (false !== options.destroyUpgrade) { | ||
// default node behavior is to disconnect when no handlers | ||
// but by adding a handler, we prevent that | ||
// and if no eio thing handles the upgrade | ||
// then the socket needs to die! | ||
setTimeout(function() { | ||
if (socket.writable && socket.bytesWritten <= 0) { | ||
return socket.end(); | ||
} | ||
}, options.destroyUpgradeTimeout); | ||
} | ||
}); | ||
} | ||
engine.attach(server, options); | ||
return engine; | ||
}; |
@@ -31,2 +31,6 @@ | ||
function Server(opts){ | ||
if (!(this instanceof Server)) { | ||
return new Server(opts); | ||
} | ||
this.clients = {}; | ||
@@ -173,3 +177,3 @@ this.clientsCount = 0; | ||
if (!success) { | ||
sendErrorMessage(res, err); | ||
sendErrorMessage(req, res, err); | ||
return; | ||
@@ -195,4 +199,12 @@ } | ||
function sendErrorMessage(res, code) { | ||
res.writeHead(400, { 'Content-Type': 'application/json' }); | ||
function sendErrorMessage(req, res, code) { | ||
var headers = { 'Content-Type': 'application/json' }; | ||
if (req.headers.origin) { | ||
headers['Access-Control-Allow-Credentials'] = 'true'; | ||
headers['Access-Control-Allow-Origin'] = req.headers.origin; | ||
} else { | ||
headers['Access-Control-Allow-Origin'] = '*'; | ||
} | ||
res.writeHead(400, headers); | ||
res.end(JSON.stringify({ | ||
@@ -231,3 +243,3 @@ code: code, | ||
catch (e) { | ||
sendErrorMessage(req.res, Server.errors.BAD_REQUEST); | ||
sendErrorMessage(req, req.res, Server.errors.BAD_REQUEST); | ||
return; | ||
@@ -321,1 +333,60 @@ } | ||
}; | ||
/** | ||
* Captures upgrade requests for a http.Server. | ||
* | ||
* @param {http.Server} server | ||
* @param {Object} options | ||
* @api public | ||
*/ | ||
Server.prototype.attach = function(server, options){ | ||
var self = this; | ||
var options = options || {}; | ||
var path = (options.path || '/engine.io').replace(/\/$/, ''); | ||
var destroyUpgrade = (options.destroyUpgrade !== undefined) ? options.destroyUpgrade : true; | ||
var destroyUpgradeTimeout = options.destroyUpgradeTimeout || 1000; | ||
// normalize path | ||
path += '/'; | ||
function check (req) { | ||
return path == req.url.substr(0, path.length); | ||
} | ||
// cache and clean up listeners | ||
var listeners = server.listeners('request').slice(0); | ||
server.removeAllListeners('request'); | ||
server.on('close', self.close.bind(self)); | ||
// add request handler | ||
server.on('request', function(req, res){ | ||
if (check(req)) { | ||
debug('intercepting request for path "%s"', path); | ||
self.handleRequest(req, res); | ||
} else { | ||
for (var i = 0, l = listeners.length; i < l; i++) { | ||
listeners[i].call(server, req, res); | ||
} | ||
} | ||
}); | ||
if(~self.transports.indexOf('websocket')) { | ||
server.on('upgrade', function (req, socket, head) { | ||
if (check(req)) { | ||
self.handleUpgrade(req, socket, head); | ||
} else if (false !== options.destroyUpgrade) { | ||
// default node behavior is to disconnect when no handlers | ||
// but by adding a handler, we prevent that | ||
// and if no eio thing handles the upgrade | ||
// then the socket needs to die! | ||
setTimeout(function() { | ||
if (socket.writable && socket.bytesWritten <= 0) { | ||
return socket.end(); | ||
} | ||
}, options.destroyUpgradeTimeout); | ||
} | ||
}); | ||
} | ||
}; |
@@ -8,2 +8,4 @@ | ||
var qs = require('querystring'); | ||
var rDoubleSlashes = /\\\\n/g; | ||
var rSlashes = /(\\)?\\n/g; | ||
@@ -47,3 +49,8 @@ /** | ||
if ('string' == typeof data) { | ||
Polling.prototype.onData.call(this, data.replace(/\\n/g, '\n')); | ||
//client will send already escaped newlines as \\\\n and newlines as \\n | ||
// \\n must be replaced with \n and \\\\n with \\n | ||
data = data.replace(rSlashes, function(match, slashes) { | ||
return slashes ? match : '\n'; | ||
}); | ||
Polling.prototype.onData.call(this, data.replace(rDoubleSlashes, '\\n')); | ||
} | ||
@@ -50,0 +57,0 @@ }; |
{ | ||
"name": "engine.io", | ||
"version": "1.2.2", | ||
"version": "1.3.0", | ||
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server", | ||
@@ -28,3 +28,3 @@ "main": "./lib/engine.io", | ||
"superagent": "0.15.4", | ||
"engine.io-client": "1.2.2", | ||
"engine.io-client": "1.3.0", | ||
"s": "0.1.1" | ||
@@ -31,0 +31,0 @@ }, |
@@ -123,2 +123,26 @@ | ||
- `()` | ||
- Returns a new `Server` instance. If the first argument is an `http.Server` then the | ||
new `Server` instance will be attached to it. Otherwise, the arguments are passed | ||
directly to the `Server` constructor. | ||
- **Parameters** | ||
- `http.Server`: optional, server to attach to. | ||
- `Object`: optional, options object (see `Server#constructor` api docs below) | ||
The following are identical ways to instantiate a server and then attach it. | ||
```js | ||
var httpServer; // previously created with `http.createServer();` from node.js api. | ||
// create a server first, and then attach | ||
var eioServer = require('engine.io').Server(); | ||
eioServer.attach(httpServer); | ||
// or call the module as a function to get `Server` | ||
var eioServer = require('engine.io')(); | ||
eioServer.attach(httpServer); | ||
// immediately attach | ||
var eioServer = require('engine.io')(http_server); | ||
``` | ||
- `listen` | ||
@@ -129,3 +153,7 @@ - Creates an `http.Server` which listens on the given port and attaches WS | ||
- `Number`: port to listen on. | ||
- `Object`: optional, options object | ||
- `Function`: callback for `listen`. | ||
- **Options** | ||
- All options from `Server.attach` method, documented below. | ||
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server | ||
- **Returns** `Server` | ||
@@ -139,7 +167,5 @@ - `attach` | ||
- **Options** | ||
- `path` (`String`): name of the path to capture (`/engine.io`). | ||
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`) | ||
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`) | ||
- **See Server options below for additional options you can pass** | ||
- **Returns** `Server` | ||
- All options from `Server.attach` method, documented below. | ||
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server | ||
- **Returns** `Server` a new Server instance. | ||
@@ -211,2 +237,13 @@ <hr><br> | ||
- **Returns** `Server` for chaining | ||
- `attach` | ||
- Attach this Server instance to an `http.Server` | ||
- Captures `upgrade` requests for a `http.Server`. In other words, makes | ||
a regular http.Server WebSocket-compatible. | ||
- **Parameters** | ||
- `http.Server`: server to attach to. | ||
- `Object`: optional, options object | ||
- **Options** | ||
- `path` (`String`): name of the path to capture (`/engine.io`). | ||
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`) | ||
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`) | ||
@@ -213,0 +250,0 @@ <hr><br> |
63146
1337
519
16