engine.io
Advanced tools
Comparing version 1.5.4 to 1.6.0
1.6.0 / 2015-11-28 | ||
================== | ||
* add support for environments that extend `Object.prototype` | ||
* remove listeners upon `clearTransport` | ||
* support for all versions of node | ||
* fix linering sockets that can stay open when upgrade failed | ||
* ensure sockets are closed on error | ||
* bump `ws` for several improvements | ||
* fix for a rare race condition on some error scenarios | ||
* support custom socket id | ||
* use container-based infrastructure for faster build | ||
* fix package.json wrongly referrering to self | ||
* allow overriding the `cookiePath` | ||
* fix potential encoding errors under certain conditions | ||
* support compression | ||
1.5.4 / 2015-09-09 | ||
@@ -34,4 +51,4 @@ ================== | ||
* package: bump `ws` to fix fd leaks | ||
* socket: flush the write buffer before closing the socket [nkzawa] | ||
* polling: close the pending poll request when closing transport [nkzawa] | ||
* socket: flush the write buffer before closing the socket [lpinca] | ||
* polling: close the pending poll request when closing transport [lpinca] | ||
@@ -38,0 +55,0 @@ 1.4.2 / 2014-10-08 |
@@ -48,3 +48,3 @@ /** | ||
/** | ||
* Expose Server constructor. | ||
* Expose Socket constructor. | ||
* | ||
@@ -51,0 +51,0 @@ * @api public |
@@ -47,6 +47,18 @@ | ||
this.cookie = false !== opts.cookie ? (opts.cookie || 'io') : false; | ||
this.cookiePath = false !== opts.cookiePath ? (opts.cookiePath || false) : false; | ||
this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || true) : false; | ||
this.httpCompression = false !== opts.httpCompression ? (opts.httpCompression || {}) : false; | ||
if (true === this.httpCompression) this.httpCompression = {}; | ||
if (this.httpCompression && null == this.httpCompression.threshold) { | ||
this.httpCompression.threshold = 1024; | ||
} | ||
// initialize websocket server | ||
if (~this.transports.indexOf('websocket')) { | ||
this.ws = new WebSocketServer({ noServer: true, clientTracking: false }); | ||
this.ws = new WebSocketServer({ | ||
noServer: true, | ||
clientTracking: false, | ||
perMessageDeflate: this.perMessageDeflate | ||
}); | ||
} | ||
@@ -156,3 +168,5 @@ } | ||
for (var i in this.clients) { | ||
this.clients[i].close(); | ||
if (this.clients.hasOwnProperty(i)) { | ||
this.clients[i].close(); | ||
} | ||
} | ||
@@ -216,2 +230,14 @@ return this; | ||
/** | ||
* generate a socket id. | ||
* Overwrite this method to generate your custom socket id | ||
* | ||
* @param {Object} request object | ||
* @api public | ||
*/ | ||
Server.prototype.generateId = function(req){ | ||
return base64id.generateId(); | ||
}; | ||
/** | ||
* Handshakes a new client. | ||
@@ -225,3 +251,3 @@ * | ||
Server.prototype.handshake = function(transport, req){ | ||
var id = base64id.generateId(); | ||
var id = this.generateId(req); | ||
@@ -235,2 +261,3 @@ debug('handshaking client "%s"', id); | ||
transport.maxHttpBufferSize = this.maxHttpBufferSize; | ||
transport.httpCompression = this.httpCompression; | ||
} | ||
@@ -253,3 +280,7 @@ | ||
transport.on('headers', function(headers){ | ||
headers['Set-Cookie'] = self.cookie + '=' + id; | ||
var cookie = self.cookie + '=' + id; | ||
if(false !== self.cookiePath) { | ||
cookie += '; path=' + self.cookiePath; | ||
} | ||
headers['Set-Cookie'] = cookie; | ||
}); | ||
@@ -319,6 +350,10 @@ } | ||
if (id) { | ||
if (!this.clients[id]) { | ||
var client = this.clients[id]; | ||
if (!client) { | ||
debug('upgrade attempt for closed client'); | ||
socket.close(); | ||
} else if (this.clients[id].upgraded) { | ||
} else if (client.upgrading) { | ||
debug('transport has already been trying to upgrade'); | ||
socket.close(); | ||
} else if (client.upgraded) { | ||
debug('transport had already been upgraded'); | ||
@@ -334,3 +369,3 @@ socket.close(); | ||
} | ||
this.clients[id].maybeUpgrade(transport); | ||
client.maybeUpgrade(transport); | ||
} | ||
@@ -337,0 +372,0 @@ } else { |
@@ -23,2 +23,3 @@ /** | ||
this.server = server; | ||
this.upgrading = false; | ||
this.upgraded = false; | ||
@@ -29,2 +30,3 @@ this.readyState = 'opening'; | ||
this.sentCallbackFn = []; | ||
this.cleanupFn = []; | ||
this.request = req; | ||
@@ -144,9 +146,21 @@ | ||
Socket.prototype.setTransport = function (transport) { | ||
var onError = this.onError.bind(this); | ||
var onPacket = this.onPacket.bind(this); | ||
var flush = this.flush.bind(this); | ||
var onClose = this.onClose.bind(this, 'transport close'); | ||
this.transport = transport; | ||
this.transport.once('error', this.onError.bind(this)); | ||
this.transport.on('packet', this.onPacket.bind(this)); | ||
this.transport.on('drain', this.flush.bind(this)); | ||
this.transport.once('close', this.onClose.bind(this, 'transport close')); | ||
this.transport.once('error', onError); | ||
this.transport.on('packet', onPacket); | ||
this.transport.on('drain', flush); | ||
this.transport.once('close', onClose); | ||
//this function will manage packet events (also message callbacks) | ||
this.setupSendCallback(); | ||
this.cleanupFn.push(function() { | ||
transport.removeListener('error', onError); | ||
transport.removeListener('packet', onPacket); | ||
transport.removeListener('drain', flush); | ||
transport.removeListener('close', onClose); | ||
}); | ||
}; | ||
@@ -165,2 +179,4 @@ | ||
this.upgrading = true; | ||
var self = this; | ||
@@ -171,4 +187,3 @@ | ||
debug('client did not complete upgrade - closing transport'); | ||
clearInterval(self.checkIntervalTimer); | ||
self.checkIntervalTimer = null; | ||
cleanup(); | ||
if ('open' == transport.readyState) { | ||
@@ -181,3 +196,4 @@ transport.close(); | ||
if ('ping' == packet.type && 'probe' == packet.data) { | ||
transport.send([{ type: 'pong', data: 'probe' }]); | ||
transport.send([{ type: 'pong', data: 'probe', options: { compress: true } }]); | ||
self.emit('upgrading', transport); | ||
clearInterval(self.checkIntervalTimer); | ||
@@ -187,2 +203,3 @@ self.checkIntervalTimer = setInterval(check, 100); | ||
debug('got upgrade packet - upgrading'); | ||
cleanup(); | ||
self.upgraded = true; | ||
@@ -194,6 +211,2 @@ self.clearTransport(); | ||
self.flush(); | ||
clearInterval(self.checkIntervalTimer); | ||
self.checkIntervalTimer = null; | ||
clearTimeout(self.upgradeTimeoutTimer); | ||
transport.removeListener('packet', onPacket); | ||
if (self.readyState == 'closing') { | ||
@@ -205,2 +218,3 @@ transport.close(function () { | ||
} else { | ||
cleanup(); | ||
transport.close(); | ||
@@ -214,7 +228,41 @@ } | ||
debug('writing a noop packet to polling for fast upgrade'); | ||
self.transport.send([{ type: 'noop' }]); | ||
self.transport.send([{ type: 'noop', options: { compress: true } }]); | ||
} | ||
} | ||
function cleanup() { | ||
self.upgrading = false; | ||
clearInterval(self.checkIntervalTimer); | ||
self.checkIntervalTimer = null; | ||
clearTimeout(self.upgradeTimeoutTimer); | ||
self.upgradeTimeoutTimer = null; | ||
transport.removeListener('packet', onPacket); | ||
transport.removeListener('close', onTransportClose); | ||
transport.removeListener('error', onError); | ||
self.removeListener('close', onClose); | ||
} | ||
function onError(err) { | ||
debug('client did not complete upgrade - %s', err); | ||
cleanup(); | ||
transport.close(); | ||
transport = null; | ||
} | ||
function onTransportClose(){ | ||
onError("transport closed"); | ||
} | ||
function onClose() { | ||
onError("socket closed"); | ||
} | ||
transport.on('packet', onPacket); | ||
transport.once('close', onTransportClose); | ||
transport.once('error', onError); | ||
self.once('close', onClose); | ||
}; | ||
@@ -229,2 +277,5 @@ | ||
Socket.prototype.clearTransport = function () { | ||
var cleanup; | ||
while (cleanup = this.cleanupFn.shift()) cleanup(); | ||
// silence further transport errors and prevent uncaught exceptions | ||
@@ -234,2 +285,6 @@ this.transport.on('error', function(){ | ||
}); | ||
// ensure transport won't stay open | ||
this.transport.close(); | ||
clearTimeout(this.pingTimeoutTimer); | ||
@@ -246,2 +301,3 @@ }; | ||
if ('closed' != this.readyState) { | ||
this.readyState = 'closed'; | ||
clearTimeout(this.pingTimeoutTimer); | ||
@@ -260,3 +316,2 @@ clearInterval(this.checkIntervalTimer); | ||
this.clearTransport(); | ||
this.readyState = 'closed'; | ||
this.emit('close', reason, description); | ||
@@ -274,4 +329,10 @@ } | ||
var self = this; | ||
this.transport.on('drain', onDrain); | ||
this.cleanupFn.push(function() { | ||
self.transport.removeListener('drain', onDrain); | ||
}); | ||
//the message was sent successfully, execute the callback | ||
this.transport.on('drain', function() { | ||
function onDrain() { | ||
if (self.sentCallbackFn.length > 0) { | ||
@@ -291,3 +352,3 @@ var seqFn = self.sentCallbackFn.splice(0,1)[0]; | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -299,2 +360,3 @@ | ||
* @param {String} message | ||
* @param {Object} options | ||
* @param {Function} callback | ||
@@ -306,4 +368,4 @@ * @return {Socket} for chaining | ||
Socket.prototype.send = | ||
Socket.prototype.write = function(data, callback){ | ||
this.sendPacket('message', data, callback); | ||
Socket.prototype.write = function(data, options, callback){ | ||
this.sendPacket('message', data, options, callback); | ||
return this; | ||
@@ -317,10 +379,22 @@ }; | ||
* @param {String} optional, data | ||
* @param {Object} options | ||
* @api private | ||
*/ | ||
Socket.prototype.sendPacket = function (type, data, callback) { | ||
Socket.prototype.sendPacket = function (type, data, options, callback) { | ||
if ('function' == typeof options) { | ||
callback = options; | ||
options = null; | ||
} | ||
options = options || {}; | ||
options.compress = false !== options.compress; | ||
if ('closing' != this.readyState) { | ||
debug('sending packet "%s" (%s)', type, data); | ||
var packet = { type: type }; | ||
var packet = { | ||
type: type, | ||
options: options | ||
}; | ||
if (data) packet.data = data; | ||
@@ -327,0 +401,0 @@ |
@@ -32,3 +32,3 @@ | ||
function Transport (req) { | ||
this.readyState = 'opening'; | ||
this.readyState = 'open'; | ||
}; | ||
@@ -61,2 +61,4 @@ | ||
Transport.prototype.close = function (fn) { | ||
if ('closed' == this.readyState || 'closing' == this.readyState) return; | ||
this.readyState = 'closing'; | ||
@@ -63,0 +65,0 @@ this.doClose(fn || noop); |
@@ -63,3 +63,3 @@ | ||
JSONP.prototype.doWrite = function (data) { | ||
JSONP.prototype.doWrite = function (data, options, callback) { | ||
// we must output valid javascript, not valid json | ||
@@ -74,17 +74,3 @@ // see: http://timelessrepo.com/json-isnt-a-javascript-subset | ||
// explicit UTF-8 is required for pages not served under utf | ||
var headers = { | ||
'Content-Type': 'text/javascript; charset=UTF-8', | ||
'Content-Length': Buffer.byteLength(data) | ||
}; | ||
// prevent XSS warnings on IE | ||
// https://github.com/LearnBoost/socket.io/pull/1333 | ||
var ua = this.req.headers['user-agent']; | ||
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) { | ||
headers['X-XSS-Protection'] = '0'; | ||
} | ||
this.res.writeHead(200, this.headers(this.req, headers)); | ||
this.res.end(data); | ||
Polling.prototype.doWrite.call(this, data, options, callback); | ||
}; | ||
@@ -91,0 +77,0 @@ |
@@ -52,32 +52,2 @@ | ||
/** | ||
* Frames data prior to write. | ||
* | ||
* @api private | ||
*/ | ||
XHR.prototype.doWrite = function(data){ | ||
// explicit UTF-8 is required for pages not served under utf | ||
var isString = typeof data == 'string'; | ||
var contentType = isString | ||
? 'text/plain; charset=UTF-8' | ||
: 'application/octet-stream'; | ||
var contentLength = '' + (isString ? Buffer.byteLength(data) : data.length); | ||
var headers = { | ||
'Content-Type': contentType, | ||
'Content-Length': contentLength | ||
}; | ||
// prevent XSS warnings on IE | ||
// https://github.com/LearnBoost/socket.io/pull/1333 | ||
var ua = this.req.headers['user-agent']; | ||
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) { | ||
headers['X-XSS-Protection'] = '0'; | ||
} | ||
this.res.writeHead(200, this.headers(this.req, headers)); | ||
this.res.end(data); | ||
}; | ||
/** | ||
* Returns headers for a response. | ||
@@ -84,0 +54,0 @@ * |
@@ -8,4 +8,11 @@ | ||
, parser = require('engine.io-parser') | ||
, zlib = require('zlib') | ||
, accepts = require('accepts') | ||
, debug = require('debug')('engine:polling'); | ||
var compressionMethods = { | ||
gzip: zlib.createGzip, | ||
deflate: zlib.createDeflate | ||
}; | ||
/** | ||
@@ -25,2 +32,4 @@ * Exports the constructor. | ||
Transport.call(this, req); | ||
this.closeTimeout = 30 * 1000; | ||
} | ||
@@ -76,2 +85,3 @@ | ||
res.writeHead(500); | ||
res.end(); | ||
return; | ||
@@ -105,3 +115,3 @@ } | ||
debug('triggering empty send to append close packet'); | ||
this.send([{ type: 'noop' }]); | ||
this.send([{ type: 'noop', options: { compress: true } }]); | ||
} | ||
@@ -121,2 +131,3 @@ }; | ||
res.writeHead(500); | ||
res.end(); | ||
return; | ||
@@ -185,5 +196,5 @@ } | ||
req.on('close', onClose); | ||
if (!isBinary) req.setEncoding('utf8'); | ||
req.on('data', onData); | ||
req.on('end', onEnd); | ||
if (!isBinary) req.setEncoding('utf8'); | ||
}; | ||
@@ -223,3 +234,3 @@ | ||
// close pending poll request | ||
this.send([{ type: 'noop' }]); | ||
this.send([{ type: 'noop', options: { compress: true } }]); | ||
} | ||
@@ -237,5 +248,7 @@ Transport.prototype.onClose.call(this); | ||
Polling.prototype.send = function (packets) { | ||
this.writable = false; | ||
if (this.shouldClose) { | ||
debug('appending close packet to payload'); | ||
packets.push({ type: 'close' }); | ||
packets.push({ type: 'close', options: { compress: true } }); | ||
this.shouldClose(); | ||
@@ -247,3 +260,6 @@ this.shouldClose = null; | ||
parser.encodePayload(packets, this.supportsBinary, function(data) { | ||
self.write(data); | ||
var compress = packets.some(function(packet) { | ||
return packet.options && packet.options.compress; | ||
}); | ||
self.write(data, { compress: compress }); | ||
}); | ||
@@ -256,13 +272,102 @@ }; | ||
* @param {String} data | ||
* @param {Object} options | ||
* @api private | ||
*/ | ||
Polling.prototype.write = function (data) { | ||
Polling.prototype.write = function (data, options) { | ||
debug('writing "%s"', data); | ||
this.doWrite(data); | ||
this.req.cleanup(); | ||
this.writable = false; | ||
var self = this; | ||
this.doWrite(data, options, function() { | ||
self.req.cleanup(); | ||
}); | ||
}; | ||
/** | ||
* Performs the write. | ||
* | ||
* @api private | ||
*/ | ||
Polling.prototype.doWrite = function (data, options, callback) { | ||
var self = this; | ||
// explicit UTF-8 is required for pages not served under utf | ||
var isString = typeof data == 'string'; | ||
var contentType = isString | ||
? 'text/plain; charset=UTF-8' | ||
: 'application/octet-stream'; | ||
var headers = { | ||
'Content-Type': contentType | ||
}; | ||
// prevent XSS warnings on IE | ||
// https://github.com/LearnBoost/socket.io/pull/1333 | ||
var ua = this.req.headers['user-agent']; | ||
if (ua && (~ua.indexOf(';MSIE') || ~ua.indexOf('Trident/'))) { | ||
headers['X-XSS-Protection'] = '0'; | ||
} | ||
if (!this.httpCompression || !options.compress) { | ||
respond(data); | ||
return; | ||
} | ||
var len = isString ? Buffer.byteLength(data) : data.length; | ||
if (len < this.httpCompression.threshold) { | ||
respond(data); | ||
return; | ||
} | ||
var encoding = accepts(this.req).encodings(['gzip', 'deflate']); | ||
if (!encoding) { | ||
respond(data); | ||
return; | ||
} | ||
this.compress(data, encoding, function(err, data) { | ||
if (err) { | ||
self.res.writeHead(500); | ||
self.res.end(); | ||
callback(err); | ||
return; | ||
} | ||
headers['Content-Encoding'] = encoding; | ||
respond(data); | ||
}); | ||
function respond(data) { | ||
headers['Content-Length'] = 'string' == typeof data ? Buffer.byteLength(data) : data.length; | ||
self.res.writeHead(200, self.headers(self.req, headers)); | ||
self.res.end(data); | ||
callback(); | ||
} | ||
}; | ||
/** | ||
* Comparesses data. | ||
* | ||
* @api private | ||
*/ | ||
Polling.prototype.compress = function (data, encoding, callback) { | ||
debug('compressing'); | ||
var buffers = []; | ||
var nread = 0; | ||
compressionMethods[encoding](this.httpCompression) | ||
.on('error', callback) | ||
.on('data', function(chunk) { | ||
buffers.push(chunk); | ||
nread += chunk.length; | ||
}) | ||
.on('end', function() { | ||
callback(null, Buffer.concat(buffers, nread)); | ||
}) | ||
.end(data); | ||
}; | ||
/** | ||
* Closes the transport. | ||
@@ -276,2 +381,5 @@ * | ||
var self = this; | ||
var closeTimeoutTimer; | ||
if (this.dataReq) { | ||
@@ -284,8 +392,15 @@ debug('aborting ongoing data request'); | ||
debug('transport writable - closing right away'); | ||
this.send([{ type: 'close' }]); | ||
fn(); | ||
this.send([{ type: 'close', options: { compress: true } }]); | ||
onClose(); | ||
} else { | ||
debug('transport not writable - buffering orderly close'); | ||
this.shouldClose = fn; | ||
this.shouldClose = onClose; | ||
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout); | ||
} | ||
function onClose() { | ||
clearTimeout(closeTimeoutTimer); | ||
fn(); | ||
self.onClose(); | ||
} | ||
}; |
@@ -87,7 +87,7 @@ | ||
var self = this; | ||
for (var i = 0, l = packets.length; i < l; i++) { | ||
parser.encodePacket(packets[i], this.supportsBinary, function(data) { | ||
packets.forEach(function(packet) { | ||
parser.encodePacket(packet, self.supportsBinary, function(data) { | ||
debug('writing "%s"', data); | ||
self.writable = false; | ||
self.socket.send(data, function (err){ | ||
self.socket.send(data, packet.options, function (err){ | ||
if (err) return self.onError('write error', err.stack); | ||
@@ -98,3 +98,3 @@ self.writable = true; | ||
}); | ||
} | ||
}); | ||
}; | ||
@@ -101,0 +101,0 @@ |
{ | ||
"name": "engine.io", | ||
"version": "1.5.4", | ||
"version": "1.6.0", | ||
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server", | ||
"main": "./lib/engine.io", | ||
"author": "Guillermo Rauch <guillermo@learnboost.com>", | ||
"homepage": "https://github.com/LearnBoost/engine.io", | ||
"homepage": "https://github.com/socketio/engine.io", | ||
"contributors": [ | ||
@@ -26,14 +26,16 @@ { | ||
], | ||
"license": "MIT", | ||
"dependencies": { | ||
"base64id": "0.1.0", | ||
"debug": "1.0.3", | ||
"debug": "2.2.0", | ||
"ws": "0.8.0", | ||
"engine.io-parser": "1.2.2", | ||
"ws": "0.8.0" | ||
"accepts": "1.1.4" | ||
}, | ||
"devDependencies": { | ||
"mocha": "1.12.0", | ||
"engine.io-client": "1.6.0", | ||
"expect.js": "0.2.0", | ||
"superagent": "0.15.4", | ||
"engine.io-client": "1.5.4", | ||
"s": "0.1.1" | ||
"mocha": "2.3.4", | ||
"s": "0.1.1", | ||
"superagent": "0.15.4" | ||
}, | ||
@@ -45,4 +47,4 @@ "scripts": { | ||
"type": "git", | ||
"url": "git@github.com:Automattic/engine.io.git" | ||
"url": "git@github.com:socketio/engine.io.git" | ||
} | ||
} |
# Engine.IO: the realtime engine | ||
[![Build Status](https://secure.travis-ci.org/Automattic/engine.io.png)](http://travis-ci.org/Automattic/engine.io) | ||
[![NPM version](https://badge.fury.io/js/engine.io.png)](http://badge.fury.io/js/engine.io) | ||
[![Build Status](https://secure.travis-ci.org/socketio/engine.io.svg)](http://travis-ci.org/socketio/engine.io) | ||
[![NPM version](https://badge.fury.io/js/engine.io.svg)](http://badge.fury.io/js/engine.io) | ||
`Engine.IO` is the implementation of transport-based | ||
cross-browser/cross-device bi-directional communication layer for | ||
[Socket.IO](http://github.com/learnboost/socket.io). | ||
[Socket.IO](http://github.com/socketio/socket.io). | ||
@@ -215,5 +215,13 @@ ## How to use | ||
(`true`) | ||
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension | ||
(see [ws module](https://github.com/einaros/ws) api docs). Set to `false` to disable. (`true`) | ||
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports | ||
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`) | ||
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`) | ||
- `cookie` (`String|Boolean`): name of the HTTP cookie that | ||
contains the client sid to send as part of handshake response | ||
headers. Set to `false` to not send one. (`io`) | ||
- `cookiePath` (`String|Boolean`): path of the above `cookie` | ||
option. If false, no path will be sent, which means browsers will only send the cookie on the engine.io attached path (`/engine.io`). | ||
Set this to `/` to send the io cookie on all requests. (`false`) | ||
- `close` | ||
@@ -246,2 +254,8 @@ - Closes all clients | ||
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`) | ||
- `generateId` | ||
- Generate a socket id. | ||
- Overwrite this method to generate your custom socket id. | ||
- **Parameters** | ||
- `http.ServerRequest`: a node request object | ||
- **Returns** A socket id for connected client. | ||
@@ -302,3 +316,6 @@ <hr><br> | ||
- `String` | `Buffer` | `ArrayBuffer` | `ArrayBufferView`: a string or any object implementing `toString()`, with outgoing data, or a Buffer or ArrayBuffer with binary data. Also any ArrayBufferView can be sent as is. | ||
- `Object`: optional, options object | ||
- `Function`: optional, a callback executed when the message gets flushed out by the transport | ||
- **Options** | ||
- `compress` (`Boolean`): whether to compress sending data. This option might be ignored and forced to be `true` when using polling. (`true`) | ||
- **Returns** `Socket` for chaining | ||
@@ -316,3 +333,3 @@ - `close` | ||
For the client API refer to the | ||
For the client API refer to the | ||
[engine-client](http://github.com/learnboost/engine.io-client) repository. | ||
@@ -396,3 +413,3 @@ | ||
- _B: Network traffic_<br> | ||
WebSocket is designed around the premise that each message frame has to be | ||
WebSocket is designed around the premise that each message frame has to be | ||
surrounded by the least amount of data. In HTTP 1.1 transports, each message | ||
@@ -431,3 +448,3 @@ frame is surrounded by HTTP headers and chunked encoding frames. If you try to | ||
nature of the evolution of the WebSocket protocol. Applications therefore end up | ||
inevitably using long polling, but the seamless installation experience of | ||
inevitably using long polling, but the seamless installation experience of | ||
Socket.IO we strive for (_"require() it and it just works"_) disappears. | ||
@@ -474,3 +491,3 @@ | ||
Absolutely. Although the recommended framework for building realtime applications | ||
is Socket.IO, since it provides fundamental features for real-world applications | ||
is Socket.IO, since it provides fundamental features for real-world applications | ||
such as multiplexing, reconnection support, etc. | ||
@@ -500,3 +517,3 @@ | ||
## License | ||
## License | ||
@@ -525,2 +542,1 @@ (The MIT License) | ||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
72951
17
0
1519
534
5
+ Addedaccepts@1.1.4
+ Addedaccepts@1.1.4(transitive)
+ Addeddebug@2.2.0(transitive)
+ Addedmime-db@1.12.0(transitive)
+ Addedmime-types@2.0.14(transitive)
+ Addedms@0.7.1(transitive)
+ Addednegotiator@0.4.9(transitive)
- Removeddebug@1.0.3(transitive)
- Removedms@0.6.2(transitive)
Updateddebug@2.2.0