Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

primus

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

primus - npm Package Compare versions

Comparing version 1.5.2 to 2.0.0

66

index.js
'use strict';
var EventEmitter = require('events').EventEmitter
, PrimusError = require('./errors').PrimusError
var PrimusError = require('./errors').PrimusError
, EventEmitter = require('eventemitter3')
, Transformer = require('./transformer')

@@ -20,2 +20,7 @@ , Spark = require('./spark')

if (!(this instanceof Primus)) return new Primus(server, options);
if ('object' !== typeof server) {
var message = 'The first argument of the constructor must be ' +
'an HTTP or HTTPS server instance';
throw new PrimusError(message, this);
}

@@ -30,5 +35,8 @@ options = options || {};

this.sparks = 0; // Increment id for connection ids.
this.connected = 0; // Connection counter .
this.connected = 0; // Connection counter.
this.connections = Object.create(null); // Connection storage.
this.ark = Object.create(null); // Plugin storage.
this.timeout = 'timeout' in options // The timeout used to detect zombie sparks.
? options.timeout
: 35000;
this.whitelist = []; // Forwarded-for whitelisting.

@@ -103,3 +111,3 @@ this.options = options; // The configuration.

__filename: 'primus.js',
__dirname: __dirname
__dirname: process.cwd()
}).Primus;

@@ -351,3 +359,3 @@ }

var client = '(function (name, context, definition) {'
+ ' context[name] = definition();'
+ ' context[name] = definition.call(context);'
+ ' if (typeof module !== "undefined" && module.exports) {'

@@ -373,2 +381,12 @@ + ' module.exports = context[name];'

//
// As we're given a timeout value on the server side, we need to update the
// `ping` interval of the client to ensure that we've sent the server
// a message before the timeout gets triggered and we get disconnected.
//
if ('number' === typeof this.timeout) {
var timeout = this.timeout - 10000;
client = client.replace('options.ping : 25e3;', 'options.ping : '+ timeout +';');
}
//
// Add the parser inside the closure, to prevent global leaking.

@@ -401,3 +419,13 @@ //

//
return client +' return Primus; });'+ library.filter(Boolean).join('\n');
return client +' return Primus; });' + library
.filter(Boolean)
.map(function wrap(lib) {
//
// Wrap the libraries in a closure, they could expose variables or
// override variables that are used by the application. A good example of
// this is the use of the `require` function which requirejs, browserify
// and others are using.
//
return '(function library(Primus, global) {'+ lib +'}(this.Primus, this));';
}).join('\n');
};

@@ -582,2 +610,28 @@

/**
* Checks if the given event is an emitted event by Primus.
*
* @param {String} evt The event name.
* @returns {Boolean}
* @api public
*/
Primus.prototype.reserved = function reserved(evt) {
return (/^(incoming|outgoing)::/).test(evt)
|| evt in reserved.events;
};
/**
* The actual events that are used by Primus.
*
* @type {Object}
* @api public
*/
Primus.prototype.reserved.events = {
disconnection: 1,
initialised: 1,
connection: 1,
close: 1,
log: 1
};
/**
* Add a createSocket interface so we can create a Server client with the

@@ -584,0 +638,0 @@ * specified `transformer` and `parser`.

8

package.json
{
"name": "primus",
"version": "1.5.2",
"version": "2.0.0",
"description": "Primus is a simple abstraction around real-time frameworks. It allows you to easily switch between different frameworks without any code changes.",

@@ -28,4 +28,6 @@ "main": "index.js",

"dependencies": {
"extendable": "0.0.x",
"load": "1.0.x"
"load": "1.0.x",
"predefine": "0.0.x",
"eventemitter3": "0.1.x",
"forwarded-for": "0.0.x"
},

@@ -32,0 +34,0 @@ "devDependencies": {

/*globals require, define */
'use strict';
//
// Sets the default connection URL, it uses the default origin of the browser
// when supported but degrades for older browsers. In Node.js, we cannot guess
// where the user wants to connect to, so we just default to localhost.
//
var defaultUrl;
try {
if (location.origin) {
defaultUrl = location.origin;
} else {
defaultUrl = location.protocol +'//'+ location.hostname + (location.port ? ':'+ location.port : '');
}
} catch (e) {
defaultUrl = 'http://127.0.0.1';
}
/**

@@ -40,3 +23,3 @@ * Minimal EventEmitter interface that is molded against the Node.js

EventEmitter.prototype.listeners = function listeners(event) {
return (this._events[event] || []).slice(0);
return Array.apply(this, this._events[event] || []);
};

@@ -52,8 +35,8 @@

EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
if (!this._events[event]) return false;
if (!this._events || !this._events[event]) return false;
var listeners = this._events[event]
, length = listeners.length
, handler = listeners[0]
, len = arguments.length
, fn = listeners[0]
, args

@@ -65,18 +48,18 @@ , i;

case 1:
handler.call(this);
fn.call(fn.context || this);
break;
case 2:
handler.call(this, a1);
fn.call(fn.context || this, a1);
break;
case 3:
handler.call(this, a1, a2);
fn.call(fn.context || this, a1, a2);
break;
case 4:
handler.call(this, a1, a2, a3);
fn.call(fn.context || this, a1, a2, a3);
break;
case 5:
handler.call(this, a1, a2, a3, a4);
fn.call(fn.context || this, a1, a2, a3, a4);
break;
case 6:
handler.call(this, a1, a2, a3, a4, a5);
fn.call(fn.context || this, a1, a2, a3, a4, a5);
break;

@@ -89,4 +72,6 @@

handler.apply(this, args);
fn.apply(fn.context || this, args);
}
if (fn.once) this.removeListener(event, fn);
} else {

@@ -97,4 +82,5 @@ for (i = 1, args = new Array(len -1); i < len; i++) {

for (i = 0; i < length; i++) {
listeners[i].apply(this, args);
for (i = 0; i < length; fn = listeners[++i]) {
fn.apply(fn.context || this, args);
if (fn.once) this.removeListener(event, fn);
}

@@ -111,6 +97,10 @@ }

* @param {Functon} fn Callback function.
* @param {Mixed} context The context of the function.
* @api public
*/
EventEmitter.prototype.on = function on(event, fn) {
EventEmitter.prototype.on = function on(event, fn, context) {
if (!this._events) this._events = {};
if (!this._events[event]) this._events[event] = [];
fn.context = context;
this._events[event].push(fn);

@@ -126,14 +116,8 @@

* @param {Function} fn Callback function.
* @param {Mixed} context The context of the function.
* @api public
*/
EventEmitter.prototype.once = function once(event, fn) {
var ee = this;
function eject() {
ee.removeListener(event, eject);
fn.apply(ee, arguments);
}
eject.fn = fn;
return ee.on(event, eject);
EventEmitter.prototype.once = function once(event, fn, context) {
fn.once = true;
return this.on(event, fn, context);
};

@@ -155,3 +139,3 @@

for (var i = 0, length = listeners.length; i < length; i++) {
if (!(!fn || listeners[i] === fn || listeners[i].fn === fn)) {
if (fn && listeners[i] !== fn && listeners[i].fn !== fn) {
events.push(listeners[i]);

@@ -177,2 +161,4 @@ }

EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
if (!this._events) return this;
if (event) this._events[event] = null;

@@ -184,2 +170,15 @@ else this._events = {};

//
// Alias methods names because people roll like that.
//
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
//
// This function doesn't apply anymore.
//
EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
return this;
};
/**

@@ -198,6 +197,26 @@ * Context assertion, ensure that some of our public Primus methods are called

if (!self.listeners('error').length) throw failure;
if ('function' !== typeof self.listeners || !self.listeners('error').length) {
throw failure;
}
self.emit('error', failure);
}
//
// Sets the default connection URL, it uses the default origin of the browser
// when supported but degrades for older browsers. In Node.js, we cannot guess
// where the user wants to connect to, so we just default to localhost.
//
var defaultUrl;
try {
if (location.origin) {
defaultUrl = location.origin;
} else {
defaultUrl = location.protocol +'//'+ location.hostname + (location.port ? ':'+ location.port : '');
}
} catch (e) {
defaultUrl = 'http://127.0.0.1';
}
/**

@@ -217,2 +236,3 @@ * Primus in a real-time library agnostic framework for establishing real-time

* - transport, Transport options.
* - url, uri, The URL to use connect with the server.
*

@@ -222,3 +242,3 @@ * @constructor

* @param {Object} options The configuration.
* @api private
* @api public
*/

@@ -228,13 +248,29 @@ function Primus(url, options) {

if ('object' === typeof url) {
options = url;
url = options.url || options.uri || defaultUrl;
} else {
options = options || {};
}
var primus = this;
options = options || {};
options.timeout = +options.timeout || 10e3; // Connection timeout duration.
options.reconnect = options.reconnect || {}; // Stores the back off configuration.
options.ping = +options.ping || 25e3; // Heartbeat ping interval.
options.pong = +options.pong || 10e3; // Heartbeat pong response timeout.
options.strategy = 'strategy' in options // Reconnect strategies, supplying
? options.strategy
: [];
// Connection timeout duration.
options.timeout = 'timeout' in options ? options.timeout : 10e3;
// Stores the back off configuration.
options.reconnect = 'reconnect' in options ? options.reconnect : {};
// Heartbeat ping interval.
options.ping = 'ping' in options ? options.ping : 25e3;
// Heartbeat pong response timeout.
options.pong = 'pong' in options ? options.pong : 10e3;
// Reconnect strategies.
options.strategy = 'strategy' in options ? options.strategy : [];
// Custom transport options.
options.transport = 'transport' in options ? options.transport : {};
primus.buffer = []; // Stores premature send data.

@@ -249,2 +285,3 @@ primus.writable = true; // Silly stream compatibility.

primus.socket = null; // Reference to the internal connection.
primus.latency = 0; // Latency between messages.
primus.transport = options.transport || {}; // Transport options.

@@ -373,6 +410,6 @@ primus.transformers = { // Message transformers.

// change some parsed values. This is required if we ever want to override
// a port number etc (as browsers remove port 443 and 80 from the urls).
// a port number etc. (as browsers remove port 443 and 80 from the URL's).
//
for (key in a) {
if (a[key] && ('string' === typeof a[key] || +a[key])) {
if ('string' === typeof a[key] || 'number' === typeof a[key]) {
data[key] = a[key];

@@ -383,2 +420,15 @@ }

//
// If we don't obtain a port number (e.g. when using zombie) then try
// and guess at a value from the 'href' value
//
if (!data.port) {
if (!data.href) data.href = '';
if ((data.href.match(/\:/g) || []).length > 1) {
data.port = data.href.split(':')[2].split('/')[0];
} else {
data.port = ('https' === data.href.substr(0, 5)) ? 443 : 80;
}
}
//
// Browsers do not parse authorization information, so we need to extract

@@ -429,3 +479,6 @@ // that from the URL.

try {
if (Primus.prototype.NETWORK_EVENTS = 'onLine' in navigator && (window.addEventListener || document.body.attachEvent)) {
if (
Primus.prototype.NETWORK_EVENTS = 'onLine' in navigator
&& (window.addEventListener || document.body.attachEvent)
) {
if (!navigator.onLine) {

@@ -468,2 +521,34 @@ Primus.prototype.online = false;

/**
* Checks if the given event is an emitted event by Primus.
*
* @param {String} evt The event name.
* @returns {Boolean}
* @api public
*/
Primus.prototype.reserved = function reserved(evt) {
return (/^(incoming|outgoing)::/).test(evt)
|| evt in reserved.events;
};
/**
* The actual events that are used by the client.
*
* @type {Object}
* @api public
*/
Primus.prototype.reserved.events = {
readyStateChange: 1,
reconnecting: 1,
reconnect: 1,
offline: 1,
timeout: 1,
online: 1,
error: 1,
close: 1,
open: 1,
data: 1,
end: 1
};
/**
* Initialise the Primus and setup all parsers and internal listeners.

@@ -475,6 +560,14 @@ *

Primus.prototype.initialise = function initalise(options) {
var primus = this;
var primus = this
, start;
primus.on('outgoing::open', function opening() {
var readyState = primus.readyState;
primus.readyState = Primus.OPENING;
if (readyState !== Primus.OPENING) {
primus.emit('readyStateChange');
}
start = +new Date();
});

@@ -485,3 +578,9 @@

var readyState = primus.readyState;
primus.readyState = Primus.OPEN;
if (readyState !== Primus.OPEN) {
primus.emit('readyStateChange');
}
primus.emit('open');

@@ -497,2 +596,4 @@ primus.clearTimeout('ping', 'pong').heartbeat();

}
primus.latency = +new Date() - start;
});

@@ -503,2 +604,4 @@

primus.clearTimeout('pong').heartbeat();
primus.latency = (+new Date()) - time;
});

@@ -537,14 +640,6 @@

//
// The server is closing the connection, forcefully disconnect so we don't
// reconnect again.
// Handle all "primus::" prefixed protocol messages.
//
if ('primus::server::close' === data) return primus.end();
if (primus.protocol(data)) return;
//
// We received a pong message from the server, return the id.
//
if ('string' === typeof data && data.indexOf('primus::pong::') === 0) {
return primus.emit('incoming::pong', data.slice(14));
}
for (var i = 0, length = primus.transformers.incoming.length; i < length; i++) {

@@ -585,2 +680,6 @@ var packet = { data: data };

primus.readyState = Primus.CLOSED;
if (readyState !== Primus.CLOSED) {
primus.emit('readyStateChange');
}
if (primus.timers.connect) primus.end();

@@ -643,5 +742,7 @@ if (readyState !== Primus.OPEN) return;

function offline() {
primus.online = false;
primus.emit('offline');
primus.end();
if (!primus.online) return; // Already or still offline, bailout.
primus.online = false;
primus.emit('offline');
primus.end();
}

@@ -655,2 +756,4 @@

function online() {
if (primus.online) return; // Already or still online, bailout
primus.online = true;

@@ -674,2 +777,61 @@ primus.emit('online');

/**
* Really dead simple protocol parser. We simply assume that every message that
* is prefixed with `primus::` could be used as some sort of protocol definition
* for Primus.
*
* @param {String} msg The data.
* @returns {Boolean} Is a protocol message.
* @api private
*/
Primus.prototype.protocol = function protocol(msg) {
if (
'string' !== typeof msg
|| msg.indexOf('primus::') !== 0
) return false;
var last = msg.indexOf(':', 8)
, value = msg.slice(last + 2);
switch (msg.slice(8, last)) {
case 'pong':
this.emit('incoming::pong', value);
break;
case 'server':
//
// The server is closing the connection, forcefully disconnect so we don't
// reconnect again.
//
if ('close' === value) this.end();
break;
case 'id':
this.emit('incoming::id', value);
break;
//
// Unknown protocol, somebody is probably sending `primus::` prefixed
// messages.
//
default:
return false;
}
return true;
};
/**
* Retrieve the current id from the server.
*
* @param {Function} fn Callback function.
* @api public
*/
Primus.prototype.id = function id(fn) {
if (this.socket && this.socket.id) return fn(this.socket.id);
this.write('primus::id::');
return this.once('incoming::id', fn);
};
/**
* Establish a connection with the server. When this function is called we

@@ -762,3 +924,3 @@ * assume that we don't have any open connections. If you do call it when you

//
if (primus.online) return;
if (!primus.online) return;

@@ -950,3 +1112,8 @@ primus.online = false;

this.writable = false;
var readyState = this.readyState;
this.readyState = Primus.CLOSED;
if (readyState !== Primus.CLOSED) {
this.emit('readyStateChange');
}

@@ -1001,3 +1168,3 @@ for (var timeout in this.timers) {

* @returns {Object} Parsed connection.
* @api public
* @api private
*/

@@ -1011,3 +1178,3 @@ Primus.prototype.parse = parse;

* @returns {Object} Parsed query string.
* @api public
* @api private
*/

@@ -1122,3 +1289,5 @@ Primus.prototype.querystring = function querystring(query) {

if (!(type in this.transformers)) throw new Error('Invalid transformer type');
if (!(type in this.transformers)) {
return this.critical(new Error('Invalid transformer type'));
}

@@ -1137,3 +1306,6 @@ this.transformers[type].push(fn);

Primus.prototype.critical = function critical(err) {
if (this.listeners('error').length) return this.emit('error', err);
if (this.listeners('error').length) {
this.emit('error', err);
return this;
}

@@ -1140,0 +1312,0 @@ throw err;

# Primus
[![Build Status](https://travis-ci.org/primus/primus.png)](https://travis-ci.org/primus/primus)
[![Build Status](https://travis-ci.org/primus/primus.png?branch=master)](https://travis-ci.org/primus/primus)
[![NPM version](https://badge.fury.io/js/primus.png)](http://badge.fury.io/js/primus)

@@ -18,3 +18,3 @@

2. Built-in reconnect, it just works. The reconnect is controlled by a
randomized exponential backoff algorithm to reduce server stress.
randomised exponential back-off algorithm to reduce server stress.
3. Offline detection, Primus is smart enough to detect when users drop their

@@ -62,2 +62,3 @@ internet connection (switching WIFI points/cell towers for example) and

- [Events](#events)
- [Heartbeats and latency](#heartbeats-and-latency)
- [Supported real-time frameworks](#supported-real-time-frameworks)

@@ -77,4 +78,5 @@ - [Engine.IO](#engineio)

- [FAQ](#FAQ)
- [Scaling](#scaling)
- [Express](#express)
- [Scaling](#what-is-the-best-way-to-scale-primus)
- [Express](#how-do-i-use-primus-with-express-3)
- [RequireJS](#is-requirejs-supported)
- [Versioning](#versioning)

@@ -111,10 +113,16 @@ - [History](#history)

Name | Description | Default
--------------------|-----------------------------------------|---------------
authorization | Authorization handler | `null`
pathname | The URL namespace that Primus can own | `/primus`
parser | Message encoder for all communication | `JSON`
transformer | The tranformer we should use internally | `websockets`
plugin | The plugins that should be applied | `{}`
Name | Description | Default
--------------------|-------------------------------------------|---------------
authorization | Authorization handler | `null`
pathname | The URL namespace that Primus can own | `/primus`
parser | Message encoder for all communication | `JSON`
transformer | The tranformer we should use internally | `websockets`
plugin | The plugins that should be applied | `{}`
timeout | The heartbeat timeout | `35000`
The heartbeat timeout is used to forcefully disconnect a spark if no data is
received from the client within the specified amount of time. It is possible
to completly disable the heartbeat timeout by setting the value of the `timeout`
option to `false`.
In addition to support different frameworks we've also made it possible to use

@@ -161,3 +169,3 @@ custom encoding and decoding libraries. We're using `JSON` by default but you

extra route to the supplied HTTP server, this will serve the library for you so
you don't have to save it. Please note, that this route isn't optimized for
you don't have to save it. Please note, that this route isn't optimised for
serving static assets and should only be used during development. In your HTML

@@ -525,3 +533,3 @@ page add:

When the connection goes down unexpectedly a automatic reconnect process is
started. It's using a randomized exponential backoff algorithm to prevent
started. It's using a randomised exponential back-off algorithm to prevent
clients from DDoSing your server when you reboot as they will all be re-connecting at

@@ -604,3 +612,3 @@ different times. The reconnection can be configured using the `options` argument

But there are always use cases where reconnection is not advice for your
But there are always use cases where reconnection is not advised for your
application. In these cases we've provided a way to completely disable the

@@ -612,8 +620,6 @@ reconnection, this is done by setting the `strategy` to `false`:

```
If you want to manually control the reconnection you can call `primus.end()`
to close the connection and `primus.open()` to enstablish a new one. **Don't
do manual reconnection if you haven't set the strategy to false**.
If you want manually control the reconnecting you can should just call
`primus.end()` to close the connection and `primus.open()` to start a
connection. **Don't do manual reconnection if you haven't set the strategy to
false**.
[reconnect]: #reconnect

@@ -826,7 +832,61 @@ [strategy]: #strategy

`log` | **public** | server | Log messages.
`readyStateChange` | **public** | client/spark | The readyState has changed.
As a rule of thumb assume that every event that is prefixed with `incoming::` or
`outgoing::` is reserved for internal use only and that emitting such events your
self will most likely result in c̮̫̞͚͉̮̙͕̳̲͉̤̗̹̮̦̪̖̱h̛͍͙̖̟͕̹͕̙̦̣̲̠̪̯̳͖̝̩a̴̝̦͇̥̠̟͚̳̤̹̗̻̭͍͖͕͓̻o̥̹̮̙͔̗͍͚͓̗̦̹͈͙͕̘̮͖̝ș̗̲̤̗̮͈̙͈̹̼̣̹̖̱̤̼̺̤ ̻͙̗̥̠̱͇̱̝̟̺͍̺̼͆̅̓̓̇a̜̖͈͇͎͙̲̙̗͇̫̘̖̹͖͓͔̺̱n̹͓̮͇̯̜̤̗͍̯̰̫̫̖̰ͬ͌ͬͫd͚̪͚̭͚̥̰̤̟͎̝̲̯̭̹̭̙̼̤ ͖̞̙̹͈͚̥̦͚͉͖̼̬͓͚̳͉͙͎d̴͚̱̮̗͍̩̻̰̣̫͉͈̞̲͉̫̞͔ẻͩͦ̃͌̿̐ͪͩ̌̇͂̆̑͐ͣ ҉̲͉͔͎̤̼̘͇̮̥̻̜̹̥͚̲̻̖s̶̗̻̫̼̠̳̗̺̤̗̳͈̪̮̗̝͇͈t̙͇͕̺̱̼̤̗̰̬̣͌ͬͧ͊́ͧͩ͌r͌̐̓̃ͥ̄ͤ͑̈ͬ͆ͬ͂̇̿̅ ҉̙̼̳̭̙͍̻̱̠͈̮̺̣̝̱̙̺͉ư̳͎̻͔̯̪̝͕͚̣̜̼̞͇̠̘̠̪c̨̫͙͙̬̰̰̫̐͋͊͑̌̾̉͆t͚̗͕̝̤̗͕̲̮̝̼̺͙͚̟͓̣̥͍ĭ͙̘̩̖͇͎̆̍̿̾ͤ̔̉̈̂̾̈ͭo̬̠̝͈̺̙̮̬̗̪̤͕͇͕̰̮͖͉̬n̙̪̤̝̹͖͖̻̬̹͙̞̗͓̞̭̜̠̟
self will most likely result in c̮̫̞͚͉̮̙͕̳̲͉̤̗̹̮̦̪̖̱h̛͍͙̖̟͕̹͕̙̦̣̲̠̪̯̳͖̝̩a̴̝̦͇̥̠̟͚̳̤̹̗̻̭͍͖͕͓̻o̥̹̮̙͔̗͍͚͓̗̦̹͈͙͕̘̮͖̝ș̗̲̤̗̮͈̙͈̹̼̣̹̖̱̤̼̺̤ ̻͙̗̥̠̱͇̱̝̟̺͍̺̼͆̅̓̓̇a̜̖͈͇͎͙̲̙̗͇̫̘̖̹͖͓͔̺̱n̹͓̮͇̯̜̤̗͍̯̰̫̫̖̰ͬ͌ͬͫd͚̪͚̭͚̥̰̤̟͎̝̲̯̭̹̭̙̼̤ ͖̞̙̹͈͚̥̦͚͉͖̼̬͓͚̳͉͙͎d̴͚̱̮̗͍̩̻̰̣̫͉͈̞̲͉̫̞͔ẻͩͦ̃͌̿̐ͪͩ̌̇͂̆̑͐ͣ ҉̲͉͔͎̤̼̘͇̮̥̻̜̹̥͚̲̻̖s̶̗̻̫̼̠̳̗̺̤̗̳͈̪̮̗̝͇͈t̙͇͕̺̱̼̤̗̰̬̣͌ͬͧ͊́ͧͩ͌r͌̐̓̃ͥ̄ͤ͑̈ͬ͆ͬ͂̇̿̅ ҉̙̼̳̭̙͍̻̱̠͈̮̺̣̝̱̙̺͉ư̳͎̻͔̯̪̝͕͚̣̜̼̞͇̠̘̠̪c̨̫͙͙̬̰̰̫̐͋͊͑̌̾̉͆t͚̗͕̝̤̗͕̲̮̝̼̺͙͚̟͓̣̥͍ĭ͙̘̩̖͇͎̆̍̿̾ͤ̔̉̈̂̾̈ͭo̬̠̝͈̺̙̮̬̗̪̤͕͇͕̰̮͖͉̬n̙̪̤̝̹͖͖̻̬̹͙̞̗͓̞̭̜̠̟.
To make it easier for developers to emit events on primus it self we've added an
small helper function that checks if the event you want to emit is reserved for
Primus only. This would be all `incoming::` and `outgoing::` prefixed events and
the events listed above. This method is called `<class>.reserved()` and it's
implemented on the `Spark`:
```js
primus.on('connection', function connection(spark) {
spark.on('data', function (data) {
//
// Just imagine that we receive an array of arguments from the client which
// first argument is the name of the event that we need to emit and the
// second argument are the arguments for function.
//
if (spark.reserved(data.args[0])) return;
spark.emit.apply(spark, data.args[0]);
});
});
```
But also the client:
```js
var primus = new Primus('http://example.bar');
primus.on('data', function (data) {
if (primus.reserved(data.args[0])) return;
primus.emit.apply(primus, data.args);
});
```
And of course the `Primus` instance as well.
### Heartbeats and latency
Heartbeats are used in Primus to figure out if we still have an active, working
and reliable connection with the server. These heartbeats are send from the
**client** to the server.
the heartbeats will only be send when there is an idle connection, so there is
very little to no overhead at all. The main reason for this is that we already
know that the connection is alive when we receive data from the server.
The heartbeat package that we send over the connection is
`primus::ping::<timestamp>`. The server will echo back the exact same package.
This allows Primus to also calculate the latency between messages by simply
getting the `<timestamp>` from echo and comparing it with the local time. This
heartbeat is then stored in a `primus.latency` properly. The initial value of
the `primus.latency` is to the time it took to send an `open` package and to
actually receive a confirmation that the connection has been opened.
### Supported Real-time Frameworks

@@ -1040,3 +1100,3 @@

1. A reference to the initialized Primus server.
1. A reference to the initialised Primus server.
2. The options that were passed in the `new Primus(server, { options })`

@@ -1047,3 +1107,3 @@ constructor. So the plugin can be configured through the same interface.

1. A reference to the initialized Primus client.
1. A reference to the initialised Primus client.
2. The options that were passed in the `new Primus(url, { options })`

@@ -1263,3 +1323,18 @@ constructor. So the plugin can be configured through the same interface.

<dl>
<dt><a href="https://github.com/zeMirco/primus-express-session">primus-express-session</a></dt>
<dd>
Share a user session between Express and Primus.
</dd>
<dd>
<a href="https://travis-ci.org/zeMirco/primus-express-session">
<img src="https://travis-ci.org/zeMirco/primus-express-session.png?branch=master" alt="Build Status" />
</a>
<a href="http://badge.fury.io/js/primus-express-session">
<img src="https://badge.fury.io/js/primus-express-session.png" alt="NPM version" />
</a>
</dd>
</dl>
In addition to these community provided plugins, the Primus project also

@@ -1324,3 +1399,3 @@ provides the following plugins:

#### Scaling
#### What is the best way to scale Primus

@@ -1336,3 +1411,3 @@ Scaling Primus is as simple as sticking it behind a load balancer that supports

#### Express
#### How do I use Primus with Express 3

@@ -1360,3 +1435,3 @@ Express 3's `express()` instance isn't a valid HTTP server. In order to make it

#### Require.js
#### Is require.js supported

@@ -1411,3 +1486,3 @@ Require.js is supported to a certain degree. The `primus.js` core file should be

There isn't a steady or monthly release cycle. I usually release a new
There isn't a steady or monthly release cycle. We usually release a new
version when:

@@ -1414,0 +1489,0 @@

@@ -5,3 +5,4 @@ 'use strict';

, parse = require('querystring').parse
, forwarded = require('./forwarded')
, forwarded = require('forwarded-for')
, predefine = require('predefine')
, u2028 = /\u2028/g

@@ -24,11 +25,14 @@ , u2029 = /\u2029/g;

function Spark(primus, headers, address, query, id) {
this.primus = primus; // References to the primus.
this.headers = headers || {}; // The request headers.
this.remote = address || {}; // The remote address location.
this.query = query || {}; // The query string.
this.id = id || this.uuid(); // Unique id for socket.
this.readyState = Spark.OPEN; // The readyState of the connection.
var readable = predefine(this, predefine.READABLE)
, writable = predefine(this, predefine.WRITABLE)
, spark = this;
this.writable = true; // Silly stream compatibility.
this.readable = true; // Silly stream compatibility.
readable('primus', primus); // References to Primus.
readable('headers', headers || {}); // The request headers.
readable('remote', address || {}); // The remote address location.
readable('id', id || this.uuid()); // Unique id for socket.
readable('writable', true); // Silly stream compatibility.
readable('readable', true); // Silly stream compatibility.
writable('query', query || {}); // The query string.
writable('timeout', null); // Heartbeat timeout.

@@ -38,8 +42,14 @@ //

//
if ('string' === typeof this.query) this.query = parse(this.query);
if ('string' === typeof this.query) {
this.query = parse(this.query);
}
this.initialise();
this.heartbeat().__initialise.forEach(function execute(initialise) {
initialise.call(spark);
});
}
Spark.prototype.__proto__ = require('stream').prototype;
Spark.readable = predefine(Spark.prototype, predefine.READABLE);
Spark.writable = predefine(Spark.prototype, predefine.WRITABLE);

@@ -49,21 +59,106 @@ //

//
Spark.OPEN = 1;
Spark.CLOSED = 2;
Spark.OPENING = 1; // Only here for primus.js readyState number compatibility.
Spark.CLOSED = 2; // The connection is closed.
Spark.OPEN = 3; // The connection is open.
//
// Make sure that we emit `readyState` change events when a new readyState is
// checked. This way plugins can correctly act according to this.
//
Spark.readable('readyState', {
get: function get() {
return this.__readyState;
},
set: function set(readyState) {
if (this.__readyState === readyState) return readyState;
this.__readyState = readyState;
this.emit('readyStateChange');
return readyState;
}
}, true);
Spark.writable('__readyState', Spark.OPEN);
//
// Lazy parse interface for IP address information. As nobody is always
// interested in this, we're going to defer parsing until it's actually needed.
//
Object.defineProperty(Spark.prototype, 'address', {
get: function address() {
return forwarded(this.remote, this.headers, this.primus.whitelist);
}
Spark.readable('address', { get: function address() {
return forwarded(this.remote, this.headers, this.primus.whitelist);
}}, true);
/**
* Set a timer to forcibly disconnect the spark if no data is received from the
* client within the given timeout.
*
* @api private
*/
Spark.readable('heartbeat', function heartbeat() {
clearTimeout(this.timeout);
if ('number' !== typeof this.primus.timeout) return this;
var spark = this;
this.timeout = setTimeout(function timeout() {
if (spark.readyState === Spark.CLOSED) return;
spark.readyState = Spark.CLOSED;
spark.emit('outgoing::end');
spark.emit('end');
}, this.primus.timeout);
return this;
});
/**
* Checks if the given event is an emitted event by Primus.
*
* @param {String} evt The event name.
* @returns {Boolean}
* @api public
*/
Spark.readable('reserved', function reserved(evt) {
return (/^(incoming|outgoing)::/).test(evt)
|| evt in reserved.events;
});
/**
* The actual events that are used by the Spark.
*
* @type {Object}
* @api public
*/
Spark.prototype.reserved.events = {
readyStateChange: 1,
error: 1,
data: 1,
end: 1
};
/**
* Allows for adding initialise listeners without people overriding our default
* initializer. If they are feeling adventures and really want want to hack it
* up, they can remove it from the __initialise array.
*
* @returns {Function} The last added initialise hook.
* @api public
*/
Spark.readable('initialise', {
get: function get() {
return this.__initialise[this.__initialise.length - 1];
},
set: function set(initialise) {
if ('function' === typeof initialise) this.__initialise.push(initialise);
}
}, true);
/**
* Attach hooks and automatically announce a new connection.
*
* @type {Array}
* @api private
*/
Spark.prototype.initialise = function initialise() {
Spark.readable('__initialise', [function initialise() {
var primus = this.primus

@@ -73,5 +168,17 @@ , spark = this;

//
// Prevent double initialization of the spark. If we already have an
// `incoming::data` handler we assume that all other cases are handled as well.
//
if (this.listeners('incoming::data').length) return;
//
// We've received new data from our client, decode and emit it.
//
spark.on('incoming::data', function message(raw) {
//
// New data has arrived so we're certain that the connection is still alive,
// so it's save to restart the heartbeat sequence.
//
spark.heartbeat();
primus.decoder(raw, function decoding(err, data) {

@@ -85,7 +192,5 @@ //

//
// Handle client-side heartbeats by answering them as fast as possible.
// Handle "primus::" prefixed protocol messages.
//
if ('string' === typeof data && data.indexOf('primus::ping::') === 0) {
return spark.write('primus::pong::'+ data.slice(14));
}
if (spark.protocol(data)) return;

@@ -115,2 +220,4 @@ for (var i = 0, length = primus.transformers.incoming.length; i < length; i++) {

spark.on('incoming::end', function disconnect() {
if (spark.readyState === Spark.CLOSED) return;
spark.readyState = Spark.CLOSED;

@@ -138,3 +245,4 @@ spark.emit('end');

//
spark.on('end', function () {
spark.on('end', function end() {
clearTimeout(spark.timeout);
spark.removeAllListeners();

@@ -150,15 +258,53 @@ primus.emit('disconnection', spark);

});
};
}]);
/**
* Generate a unique uuid.
* Generate a unique UUID.
*
* @returns {String} uuid.
* @returns {String} UUID.
* @api private
*/
Spark.prototype.uuid = function uuid() {
Spark.readable('uuid', function uuid() {
return Date.now() +'$'+ this.primus.sparks++;
};
});
/**
* Really dead simple protocol parser. We simply assume that every message that
* is prefixed with `primus::` could be used as some sort of protocol definition
* for Primus.
*
* @param {String} msg The data.
* @returns {Boolean} Is a protocol message.
* @api private
*/
Spark.readable('protocol', function protocol(msg) {
if (
'string' !== typeof msg
|| msg.indexOf('primus::') !== 0
) return false;
var last = msg.indexOf(':', 8)
, value = msg.slice(last + 2);
switch (msg.slice(8, last)) {
case 'ping':
this._write('primus::pong::'+ value);
break;
case 'id':
this._write('primus::id::'+ this.id);
break;
//
// Unknown protocol, somebody is probably sending `primus::` prefixed
// messages.
//
default:
return false;
}
return true;
});
/**
* Simple emit wrapper that returns a function that emits an event once it's

@@ -172,3 +318,3 @@ * called. This makes it easier for transports to emit specific events. The

*/
Spark.prototype.emits = function emits(event, parser) {
Spark.readable('emits', function emits(event, parser) {
var spark = this;

@@ -181,3 +327,3 @@

};
};
});

@@ -191,3 +337,3 @@ /**

*/
Spark.prototype.write = function write(data) {
Spark.readable('write', function write(data) {
var primus = this.primus

@@ -218,3 +364,3 @@ , packet;

return true;
};
});

@@ -227,3 +373,3 @@ /**

*/
Spark.prototype._write = function _write(data) {
Spark.readable('_write', function _write(data) {
var primus = this.primus

@@ -262,3 +408,3 @@ , spark = this;

});
};
});

@@ -271,3 +417,5 @@ /**

*/
Spark.prototype.end = function end(data) {
Spark.readable('end', function end(data) {
if (Spark.CLOSED === this.readyState) return this;
var spark = this;

@@ -287,4 +435,6 @@

});
};
return this;
});
//

@@ -291,0 +441,0 @@ // Expose the module.

'use strict';
var querystring = require('querystring').parse
, EventEmitter = require('eventemitter3')
, url = require('url').parse;

@@ -15,3 +16,3 @@

* @constructor
* @param {Primus} primus Reference to the Primus.
* @param {Primus} primus Reference to the Primus instance.
* @api public

@@ -27,6 +28,7 @@ */

EventEmitter.call(this);
this.initialise();
}
Transformer.prototype.__proto__ = require('events').EventEmitter.prototype;
Transformer.prototype.__proto__ = EventEmitter.prototype;

@@ -68,5 +70,10 @@ //

server.listeners('request').map(this.on.bind(this, 'previous::request'));
server.listeners('upgrade').map(this.on.bind(this, 'previous::upgrade'));
server.listeners('request').forEach(function each(fn) {
transformer.on('previous::request', fn);
});
server.listeners('upgrade').forEach(function each(fn) {
transformer.on('previous::upgrade', fn);
});
//

@@ -226,3 +233,3 @@ // Remove the old listeners as we want to be the first request handler for all

//
Transformer.extend = require('extendable');
Transformer.extend = require('predefine').extend;

@@ -229,0 +236,0 @@ //

'use strict';
var http = require('http');
/**

@@ -47,8 +49,11 @@ * Minimum viable Browserchannel server for Node.js that works through the primus

//
this.on('request', function request(req, res, next) {
this.on('request', function request(req, res) {
//
// The browser.channel returns a middleware layer.
//
this.service(req, res, next);
this.service(req, res, function next() {
res.writeHead(404, {'content-type': 'text/plain'});
res.end(http.STATUS_CODES[404]);
});
});
};

@@ -45,2 +45,10 @@ 'use strict';

//
// Nuke a growing memory leak as engine.io pushes instances in to an exposed
// `sockets` array.
//
if (factory.sockets && factory.sockets.length) {
factory.sockets.length = 0;
}
//
// Setup the Event handlers.

@@ -47,0 +55,0 @@ //

@@ -61,8 +61,8 @@ !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.eio=e():"undefined"!=typeof global?global.eio=e():"undefined"!=typeof self&&(self.eio=e())}(function(){var define,module,exports;

var util = require('./util')
, transports = require('./transports')
, Emitter = require('./emitter')
, debug = require('debug')('engine.io-client:socket')
, index = require('indexof')
, parser = require('engine.io-parser');
var util = require('./util');
var transports = require('./transports');
var Emitter = require('./emitter');
var debug = require('debug')('engine.io-client:socket');
var index = require('indexof');
var parser = require('engine.io-parser');

@@ -87,3 +87,3 @@ /**

function noop () {};
function noop(){}

@@ -103,3 +103,3 @@ /**

if ('object' == typeof uri) {
if (uri && 'object' == typeof uri) {
opts = uri;

@@ -138,3 +138,3 @@ uri = null;

this.timestampParam = opts.timestampParam || 't';
this.timestampRequests = !!opts.timestampRequests;
this.timestampRequests = opts.timestampRequests;
this.flashPath = opts.flashPath || '';

@@ -147,7 +147,4 @@ this.transports = opts.transports || ['polling', 'websocket', 'flashsocket'];

this.open();
}
Socket.sockets.push(this);
Socket.sockets.evs.emit('add', this);
};
/**

@@ -168,9 +165,2 @@ * Mix in `Emitter`.

/**
* Static EventEmitter.
*/
Socket.sockets = [];
Socket.sockets.evs = new Emitter;
/**
* Expose deps for legacy compatibility

@@ -242,4 +232,5 @@ * and standalone browser access.

Socket.prototype.open = function () {
var transport = this.transports[0];
this.readyState = 'opening';
var transport = this.createTransport(this.transports[0]);
var transport = this.createTransport(transport);
transport.open();

@@ -255,7 +246,8 @@ this.setTransport(transport);

Socket.prototype.setTransport = function (transport) {
Socket.prototype.setTransport = function(transport){
debug('setting transport %s', transport.name);
var self = this;
if (this.transport) {
debug('clearing existing transport');
debug('clearing existing transport %s', this.transport.name);
this.transport.removeAllListeners();

@@ -269,14 +261,14 @@ }

transport
.on('drain', function () {
self.onDrain();
})
.on('packet', function (packet) {
self.onPacket(packet);
})
.on('error', function (e) {
self.onError(e);
})
.on('close', function () {
self.onClose('transport close');
});
.on('drain', function(){
self.onDrain();
})
.on('packet', function(packet){
self.onPacket(packet);
})
.on('error', function(e){
self.onError(e);
})
.on('close', function(){
self.onClose('transport close');
});
};

@@ -328,3 +320,3 @@

err.transport = transport.name;
self.emit('error', err);
self.emit('upgradeError', err);
}

@@ -349,4 +341,4 @@ });

self.emit('error', error);
};
self.emit('upgradeError', error);
}

@@ -675,5 +667,5 @@ transport.open();

var util = require('./util')
, parser = require('engine.io-parser')
, Emitter = require('./emitter');
var util = require('./util');
var parser = require('engine.io-parser');
var Emitter = require('./emitter');

@@ -703,3 +695,3 @@ /**

this.agent = opts.agent || false;
};
}

@@ -816,2 +808,3 @@ /**

},{"./emitter":2,"./util":12,"engine.io-parser":16}],6:[function(require,module,exports){
/**

@@ -821,5 +814,5 @@ * Module dependencies.

var WS = require('./websocket')
, util = require('../util')
, debug = require('debug')('engine.io-client:flashsocket');
var WS = require('./websocket');
var util = require('../util');
var debug = require('debug')('engine.io-client:flashsocket');

@@ -850,7 +843,7 @@ /**

function FlashWS (options) {
function FlashWS(options){
WS.call(this, options);
this.flashPath = options.flashPath;
this.policyPort = options.policyPort;
};
}

@@ -877,3 +870,3 @@ /**

FlashWS.prototype.doOpen = function () {
FlashWS.prototype.doOpen = function(){
if (!this.check()) {

@@ -885,3 +878,3 @@ // let the probe timeout

// instrument websocketjs logging
function log (type) {
function log(type){
return function(){

@@ -891,10 +884,10 @@ var str = Array.prototype.join.call(arguments, ' ');

};
};
}
WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') };
WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
global.WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') };
global.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
global.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) {
WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf';
if (!global.WEB_SOCKET_SWF_LOCATION) {
global.WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf';
}

@@ -905,3 +898,3 @@

if ('undefined' == typeof swfobject) {
if (!global.swfobject) {
deps.unshift(this.flashPath + 'swfobject.js');

@@ -912,4 +905,4 @@ }

load(deps, function () {
self.ready(function () {
load(deps, function(){
self.ready(function(){
WebSocket.__addTask(function () {

@@ -929,6 +922,6 @@ self.socket = new WebSocket(self.uri());

FlashWS.prototype.doClose = function () {
FlashWS.prototype.doClose = function(){
if (!this.socket) return;
var self = this;
WebSocket.__addTask(function() {
WebSocket.__addTask(function(){
WS.prototype.doClose.call(self);

@@ -944,5 +937,5 @@ });

FlashWS.prototype.write = function() {
FlashWS.prototype.write = function(){
var self = this, args = arguments;
WebSocket.__addTask(function () {
WebSocket.__addTask(function(){
WS.prototype.write.apply(self, args);

@@ -958,9 +951,9 @@ });

FlashWS.prototype.ready = function (fn) {
FlashWS.prototype.ready = function(fn){
if (typeof WebSocket == 'undefined' ||
!('__initialize' in WebSocket) || !swfobject) {
!('__initialize' in WebSocket) || !global.swfobject) {
return;
}
if (swfobject.getFlashPlayerVersion().major < 10) {
if (global.swfobject.getFlashPlayerVersion().major < 10) {
return;

@@ -970,7 +963,8 @@ }

function init () {
// Only start downloading the swf file when the checked that this browser
// actually supports it
// only start downloading the swf file when
// we checked that this browser actually supports it
if (!FlashWS.loaded) {
if (843 != self.policyPort) {
WebSocket.loadFlashPolicyFile('xmlsocket://' + self.hostname + ':' + self.policyPort);
var policy = 'xmlsocket://' + self.hostname + ':' + self.policyPort;
WebSocket.loadFlashPolicyFile(policy);
}

@@ -1000,3 +994,3 @@

FlashWS.prototype.check = function () {
FlashWS.prototype.check = function(){
if ('undefined' == typeof window) {

@@ -1046,3 +1040,3 @@ return false;

function create (path, fn) {
function create(path, fn){
if (scripts[path]) return fn();

@@ -1054,3 +1048,3 @@

debug('loading "%s"', path);
el.onload = el.onreadystatechange = function () {
el.onload = el.onreadystatechange = function(){
if (loaded || scripts[path]) return;

@@ -1072,3 +1066,3 @@ var rs = el.readyState;

head.insertBefore(el, head.firstChild);
};
}

@@ -1082,4 +1076,4 @@ /**

function load (arr, fn) {
function process (i) {
function load(arr, fn){
function process(i){
if (!arr[i]) return fn();

@@ -1089,6 +1083,6 @@ create(arr[i], function () {

});
};
}
process(0);
};
}

@@ -1101,7 +1095,7 @@ },{"../util":12,"./websocket":11,"debug":14,"global":19}],7:[function(require,module,exports){

var XHR = require('./polling-xhr')
var XMLHttpRequest = require('xmlhttprequest')
, XHR = require('./polling-xhr')
, JSONP = require('./polling-jsonp')
, websocket = require('./websocket')
, flashsocket = require('./flashsocket')
, util = require('../util');

@@ -1145,3 +1139,4 @@ /**

xhr = util.request(xd, opts);
opts.xdomain = xd;
xhr = new XMLHttpRequest(opts);

@@ -1155,3 +1150,3 @@ if (xhr && !opts.forceJSONP) {

},{"../util":12,"./flashsocket":6,"./polling-jsonp":8,"./polling-xhr":9,"./websocket":11,"global":19}],8:[function(require,module,exports){
},{"./flashsocket":6,"./polling-jsonp":8,"./polling-xhr":9,"./websocket":11,"global":19,"xmlhttprequest":13}],8:[function(require,module,exports){

@@ -1162,4 +1157,4 @@ /**

var Polling = require('./polling')
, util = require('../util');
var Polling = require('./polling');
var util = require('../util');

@@ -1231,3 +1226,3 @@ /**

this.query.j = this.index;
};
}

@@ -1241,15 +1236,2 @@ /**

/**
* Opens the socket.
*
* @api private
*/
JSONPPolling.prototype.doOpen = function () {
var self = this;
util.defer(function () {
Polling.prototype.doOpen.call(self);
});
};
/**
* Closes the socket

@@ -1291,5 +1273,5 @@ *

script.src = this.uri();
script.onerror = function(e){
self.onError('jsonp poll error',e);
}
script.onerror = function(e){
self.onError('jsonp poll error',e);
};

@@ -1347,3 +1329,3 @@ var insertAt = document.getElementsByTagName('script')[0];

fn();
};
}

@@ -1373,3 +1355,3 @@ function initIframe () {

self.iframe = iframe;
};
}

@@ -1401,6 +1383,7 @@ initIframe();

var Polling = require('./polling')
, util = require('../util')
, Emitter = require('../emitter')
, debug = require('debug')('engine.io-client:polling-xhr');
var XMLHttpRequest = require('xmlhttprequest');
var Polling = require('./polling');
var util = require('../util');
var Emitter = require('../emitter');
var debug = require('debug')('engine.io-client:polling-xhr');

@@ -1424,3 +1407,3 @@ /**

var xobject = global[['Active'].concat('Object').join('X')];
var hasAttachEvent = global.document && global.document.attachEvent;

@@ -1455,3 +1438,3 @@ /**

}
};
}

@@ -1465,15 +1448,2 @@ /**

/**
* Opens the socket
*
* @api private
*/
XHR.prototype.doOpen = function(){
var self = this;
util.defer(function(){
Polling.prototype.doOpen.call(self);
});
};
/**
* Creates a request.

@@ -1560,39 +1530,44 @@ *

Request.prototype.create = function(){
var xhr = this.xhr = util.request(this.xd, { agent: this.agent });
var xhr = this.xhr = new XMLHttpRequest({ agent: this.agent, xdomain: this.xd });
var self = this;
xhr.open(this.method, this.uri, this.async);
try {
debug('xhr open %s: %s', this.method, this.uri);
xhr.open(this.method, this.uri, this.async);
if ('POST' == this.method) {
try {
xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
} catch (e) {}
}
if ('POST' == this.method) {
try {
xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
} catch (e) {}
}
// ie6 check
if ('withCredentials' in xhr) {
xhr.withCredentials = true;
}
// ie6 check
if ('withCredentials' in xhr) {
xhr.withCredentials = true;
}
xhr.onreadystatechange = function(){
var data;
xhr.onreadystatechange = function(){
var data;
try {
if (4 != xhr.readyState) return;
if (200 == xhr.status || 1223 == xhr.status) {
data = xhr.responseText;
} else {
self.onError(xhr.status);
try {
if (4 != xhr.readyState) return;
if (200 == xhr.status || 1223 == xhr.status) {
data = xhr.responseText;
} else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
setTimeout(function(){
self.onError(xhr.status);
}, 0);
}
} catch (e) {
self.onError(e);
}
} catch (e) {
self.onError(e);
}
if (null != data) {
self.onData(data);
}
};
if (null != data) {
self.onData(data);
}
};
debug('sending xhr with url %s | data %s', this.uri, this.data);
try {
debug('xhr data %s', this.data);
xhr.send(this.data);

@@ -1609,3 +1584,3 @@ } catch (e) {

if (xobject) {
if (hasAttachEvent) {
this.index = Request.requestsCount++;

@@ -1666,3 +1641,3 @@ Request.requests[this.index] = this;

if (xobject) {
if (hasAttachEvent) {
delete Request.requests[this.index];

@@ -1684,3 +1659,8 @@ }

if (xobject) {
/**
* Cleanup is needed for old versions of IE
* that leak memory unless we abort request before unload.
*/
if (hasAttachEvent) {
Request.requestsCount = 0;

@@ -1698,3 +1678,3 @@ Request.requests = {};

},{"../emitter":2,"../util":12,"./polling":10,"debug":14,"global":19}],10:[function(require,module,exports){
},{"../emitter":2,"../util":12,"./polling":10,"debug":14,"global":19,"xmlhttprequest":13}],10:[function(require,module,exports){
/**

@@ -1704,6 +1684,6 @@ * Module dependencies.

var Transport = require('../transport')
, util = require('../util')
, parser = require('engine.io-parser')
, debug = require('debug')('engine.io-client:polling');
var Transport = require('../transport');
var util = require('../util');
var parser = require('engine.io-parser');
var debug = require('debug')('engine.io-client:polling');

@@ -1908,5 +1888,10 @@ /**

// cache busting is forced for IE / android / iOS6 ಠ_ಠ
if (global.ActiveXObject || util.ua.chromeframe || util.ua.android || util.ua.ios6 ||
this.timestampRequests) {
query[this.timestampParam] = +new Date;
if ('ActiveXObject' in global
|| util.ua.chromeframe
|| util.ua.android
|| util.ua.ios6
|| this.timestampRequests) {
if (false !== this.timestampRequests) {
query[this.timestampParam] = +new Date;
}
}

@@ -1935,9 +1920,16 @@

var Transport = require('../transport')
, WebSocket = require('ws')
, parser = require('engine.io-parser')
, util = require('../util')
, debug = require('debug')('engine.io-client:websocket');
var Transport = require('../transport');
var parser = require('engine.io-parser');
var util = require('../util');
var debug = require('debug')('engine.io-client:websocket');
/**
* `ws` exposes a WebSocket-compatible interface in
* Node, or the `WebSocket` or `MozWebSocket` globals
* in the browser.
*/
var WebSocket = require('ws');
/**
* Module exports.

@@ -1963,3 +1955,3 @@ */

Transport.call(this, opts);
};
}

@@ -2007,3 +1999,3 @@ /**

WS.prototype.addEventListeners = function() {
WS.prototype.addEventListeners = function(){
var self = this;

@@ -2211,19 +2203,2 @@

/**
* Defers a function to ensure a spinner is not displayed by the browser.
*
* @param {Function} fn
* @api private
*/
exports.defer = function (fn) {
if (!exports.ua.webkit || 'undefined' != typeof importScripts) {
return fn();
}
exports.load(function () {
setTimeout(fn, 100);
});
};
/**
* JSON parse.

@@ -2270,10 +2245,2 @@ *

/**
* Whether the UA supports CORS for XHR.
*
* @api private
*/
exports.ua.hasCORS = require('has-cors');
/**
* Detect webkit.

@@ -2318,33 +2285,2 @@ *

/**
* XHR request helper.
*
* @param {Boolean} whether we need xdomain
* @param {Object} opts Optional "options" object
* @api private
*/
exports.request = function request (xdomain, opts) {
opts = opts || {};
opts.xdomain = xdomain;
try {
var _XMLHttpRequest = require('xmlhttprequest');
return new _XMLHttpRequest(opts);
} catch (e) {}
// XMLHttpRequest can be disabled on IE
try {
if ('undefined' != typeof XMLHttpRequest && (!xdomain || exports.ua.hasCORS)) {
return new XMLHttpRequest();
}
} catch (e) { }
if (!xdomain) {
try {
return new ActiveXObject('Microsoft.XMLHTTP');
} catch(e) { }
}
};
/**
* Parses an URI

@@ -2412,3 +2348,3 @@ *

},{"global":19,"has-cors":20,"xmlhttprequest":13}],13:[function(require,module,exports){
},{"global":19}],13:[function(require,module,exports){
// browser shim for xmlhttprequest module

@@ -2454,2 +2390,4 @@ var hasCORS = require('has-cors');

return function(fmt){
fmt = coerce(fmt);
var curr = new Date;

@@ -2557,5 +2495,16 @@ var ms = curr - (debug[name] || curr);

/**
* Coerce `val`.
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
// persist
if (window.localStorage) debug.enable(localStorage.debug);
try {
if (window.localStorage) debug.enable(localStorage.debug);
} catch(e){}

@@ -2562,0 +2511,0 @@ },{}],15:[function(require,module,exports){

@@ -13,4 +13,7 @@ 'use strict';

, Spark = this.Spark
, primus = this.primus;
, primus = this.primus
, prefix = primus.pathname;
if (prefix.charAt(prefix.length - 1) !== '/') prefix += '(?:[^/]+)?';
this.service = sockjs.createServer();

@@ -50,3 +53,3 @@

var handle = this.service.listener({
prefix: primus.pathname,
prefix: prefix,
log: this.logger.plain

@@ -53,0 +56,0 @@ }).getHandler();

'use strict';
var parse = require('url').parse;
var http = require('http')
, parse = require('url').parse;

@@ -15,3 +16,2 @@ /**

, logger = this.logger
, primus = this.primus
, Spark = this.Spark;

@@ -58,2 +58,5 @@

});
}).on('request', function request(req, res) {
res.writeHead(400, {'content-type': 'text/plain'});
res.end(http.STATUS_CODES[400]);
});

@@ -60,0 +63,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc