mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-11 16:08:24 -05:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06044efbe2 | ||
|
|
50128063de | ||
|
|
1f59e4526a | ||
|
|
0a7afa85ea | ||
|
|
1e31769062 | ||
|
|
797c9a3498 | ||
|
|
4f93a0b429 | ||
|
|
3c98130f15 | ||
|
|
9c23308c6e | ||
|
|
955e5e0d91 | ||
|
|
0ef55b26d4 | ||
|
|
4d8e2d342c | ||
|
|
d48f848bb4 | ||
|
|
57b386385e | ||
|
|
9e7567daee | ||
|
|
2e36799b17 | ||
|
|
9bb5e9de2f | ||
|
|
ff2c15de68 | ||
|
|
a483658607 | ||
|
|
4c5dbd8824 | ||
|
|
e14a10b7ce | ||
|
|
5a123beea5 | ||
|
|
2ed5f0f5fb | ||
|
|
e9f980c475 | ||
|
|
6f44f3a8ef | ||
|
|
04fc0f3677 | ||
|
|
d026c00d05 | ||
|
|
fdf64cc38f | ||
|
|
5badb6436e | ||
|
|
c20e0b26c9 | ||
|
|
5c10c5439b | ||
|
|
8182ecc61c | ||
|
|
ccd3376627 | ||
|
|
58a73d39e9 | ||
|
|
e60bd5a4da | ||
|
|
21dffa4b58 | ||
|
|
94852e3d23 | ||
|
|
b8c60506a6 | ||
|
|
ecc76f48bc |
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
*Note*: for support questions, please use one of these channels: [stackoverflow](http://stackoverflow.com/questions/tagged/socket.io) or [slack](https://socketio.slack.com)
|
||||
|
||||
### You want to:
|
||||
|
||||
* [x] report a *bug*
|
||||
* [ ] request a *feature*
|
||||
|
||||
### Current behaviour
|
||||
|
||||
|
||||
### Steps to reproduce (if the current behaviour is a bug)
|
||||
|
||||
|
||||
### Expected behaviour
|
||||
|
||||
|
||||
### Setup
|
||||
- OS:
|
||||
- browser:
|
||||
- socket.io version:
|
||||
|
||||
### Other information (e.g. stacktraces, related issues, suggestions how to fix)
|
||||
|
||||
|
||||
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
### The kind of change this PR does introduce
|
||||
|
||||
* [x] a bug fix
|
||||
* [ ] a new feature
|
||||
* [ ] an update to the documentation
|
||||
* [ ] a code change that improves performance
|
||||
* [ ] other
|
||||
|
||||
### Current behaviour
|
||||
|
||||
|
||||
### New behaviour
|
||||
|
||||
|
||||
### Other information (e.g. related issues)
|
||||
|
||||
|
||||
56
History.md
56
History.md
@@ -1,4 +1,60 @@
|
||||
|
||||
1.7.3 / 2017-02-17
|
||||
===================
|
||||
|
||||
* [chore] Bump engine.io to version 1.8.3
|
||||
|
||||
1.7.2 / 2016-12-11
|
||||
===================
|
||||
|
||||
* [chore] Bump engine.io to version 1.8.2 (#2782)
|
||||
* [fix] Fixes socket.use error packet (#2772)
|
||||
|
||||
1.7.1 / 2016-11-28
|
||||
===================
|
||||
|
||||
1.7.0 / 2016-11-27
|
||||
===================
|
||||
|
||||
* [docs] Comment connected socket availability for adapters (#2081)
|
||||
* [docs] Fixed grammar issues in the README.md (#2159)
|
||||
* [feature] serve sourcemap for socket.io-client (#2482)
|
||||
* [feature] Add a `local` flag (#2628)
|
||||
* [chore] Bump engine.io to version 1.8.1 (#2765)
|
||||
* [chore] Update client location and serve minified file (#2766)
|
||||
|
||||
1.6.0 / 2016-11-20
|
||||
==================
|
||||
|
||||
* [fix] Make ETag header comply with standard. (#2603)
|
||||
* [feature] Loading client script on demand. (#2567)
|
||||
* [test] Fix leaking clientSocket (#2721)
|
||||
* [feature] Add support for all event emitter methods (#2601)
|
||||
* [chore] Update year to 2016 (#2456)
|
||||
* [feature] Add support for socket middleware (#2306)
|
||||
* [feature] add support for Server#close(callback) (#2748)
|
||||
* [fix] Don't drop query variables on handshake (#2745)
|
||||
* [example] Add disconnection/reconnection logs to the chat example (#2675)
|
||||
* [perf] Minor code optimizations (#2219)
|
||||
* [chore] Bump debug to version 2.3.3 (#2754)
|
||||
* [chore] Bump engine.io to version 1.8.0 (#2755)
|
||||
* [chore] Bump socket.io-adapter to version 0.5.0 (#2756)
|
||||
|
||||
1.5.1 / 2016-10-24
|
||||
==================
|
||||
|
||||
* [fix] Avoid swallowing exceptions thrown by user event handlers (#2682)
|
||||
* [test] Use client function to unify `client` in test script (#2731)
|
||||
* [docs] Add link to LICENSE (#2221)
|
||||
* [docs] Fix JSDoc of optional parameters (#2465)
|
||||
* [docs] Fix typo (#2724)
|
||||
* [docs] Link readme npm package badge to npm registry page (#2612)
|
||||
* [docs] Minor fixes (#2526)
|
||||
* [chore] Bump socket.io-parser to 2.3.0 (#2730)
|
||||
* [chore] Add Github issue and PR templates (#2733)
|
||||
* [chore] Bump engine.io to 1.7.2 (#2729)
|
||||
* [chore] Bump socket.io-parser to 2.3.1 (#2734)
|
||||
|
||||
1.5.0 / 2016-10-06
|
||||
==================
|
||||
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2015 Automattic <dev@cloudup.com>
|
||||
Copyright (c) 2014-2016 Automattic <dev@cloudup.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
42
Readme.md
42
Readme.md
@@ -4,7 +4,7 @@
|
||||
[](https://travis-ci.org/socketio/socket.io)
|
||||
[](https://david-dm.org/socketio/socket.io)
|
||||
[](https://david-dm.org/socketio/socket.io#info=devDependencies)
|
||||

|
||||
[](https://www.npmjs.com/package/socket.io)
|
||||

|
||||
[](http://slack.socket.io)
|
||||
|
||||
@@ -147,7 +147,7 @@ server.listen(3000);
|
||||
__Potential drawbacks__:
|
||||
* in some situations, when it is not possible to determine `origin` it may have value of `*`
|
||||
* As this function will be executed for every request, it is advised to make this function work as fast as possible
|
||||
* If `socket.io` is used together with `Express`, the CORS headers will be affected only for `socket.io` requests. For Express can use [cors](https://github.com/expressjs/cors)
|
||||
* If `socket.io` is used together with `Express`, the CORS headers will be affected only for `socket.io` requests. For Express can use [cors](https://github.com/expressjs/cors).
|
||||
|
||||
|
||||
### Server#sockets:Namespace
|
||||
@@ -183,7 +183,7 @@ server.listen(3000);
|
||||
Initializes and retrieves the given `Namespace` by its pathname
|
||||
identifier `nsp`.
|
||||
|
||||
If the namespace was already initialized it returns it right away.
|
||||
If the namespace was already initialized it returns it immediately.
|
||||
|
||||
### Server#emit
|
||||
|
||||
@@ -198,9 +198,14 @@ server.listen(3000);
|
||||
|
||||
For other available methods, see `Namespace` below.
|
||||
|
||||
### Server#close
|
||||
### Server#close([fn:Function])
|
||||
|
||||
Closes socket.io server
|
||||
Closes socket.io server.
|
||||
|
||||
The optional `fn` is passed to the `server.close([callback])` method of the
|
||||
core `net` module and is called on error or when all connections are closed.
|
||||
The callback is expected to implement the common single argument `err`
|
||||
signature (if any).
|
||||
|
||||
```js
|
||||
var Server = require('socket.io');
|
||||
@@ -280,7 +285,7 @@ server.listen(3000);
|
||||
### Namespace#use(fn:Function):Namespace
|
||||
|
||||
Registers a middleware, which is a function that gets executed for
|
||||
every incoming `Socket` and receives as parameter the socket and a
|
||||
every incoming `Socket`, and receives as parameters the socket and a
|
||||
function to optionally defer execution to the next registered
|
||||
middleware.
|
||||
|
||||
@@ -304,6 +309,25 @@ server.listen(3000);
|
||||
It should be noted the `Socket` doesn't relate directly to the actual
|
||||
underlying TCP/IP `socket` and it is only the name of the class.
|
||||
|
||||
### Socket#use(fn:Function):Socket
|
||||
|
||||
Registers a middleware, which is a function that gets executed for
|
||||
every incoming `Packet` and receives as parameter the packet and a
|
||||
function to optionally defer execution to the next registered
|
||||
middleware.
|
||||
|
||||
```js
|
||||
var io = require('socket.io')();
|
||||
io.on('connection', function(socket){
|
||||
socket.use(function(packet, next){
|
||||
if (packet.doge === true) return next();
|
||||
next(new Error('Not a doge error'));
|
||||
});
|
||||
```
|
||||
|
||||
Errors passed to middleware callbacks are sent as special `error`
|
||||
packets to clients.
|
||||
|
||||
### Socket#rooms:Object
|
||||
|
||||
A hash of strings identifying the rooms this client is in, indexed by
|
||||
@@ -317,7 +341,7 @@ server.listen(3000);
|
||||
|
||||
A reference to the underlying `Client` transport connection (engine.io
|
||||
`Socket` object). This allows access to the IO transport layer, which
|
||||
still (mostly) asbtracts the actual TCP/IP socket.
|
||||
still (mostly) abstracts the actual TCP/IP socket.
|
||||
|
||||
### Socket#request:Request
|
||||
|
||||
@@ -424,7 +448,7 @@ These are reserved events (along with `connect`, `newListener` and `removeListen
|
||||
### Client
|
||||
|
||||
The `Client` class represents an incoming transport (engine.io)
|
||||
connection. A `Client` can be associated with many multiplexed `Socket`
|
||||
connection. A `Client` can be associated with many multiplexed `Socket`s
|
||||
that belong to different `Namespace`s.
|
||||
|
||||
### Client#conn
|
||||
@@ -462,4 +486,4 @@ The `gulp` task `test` will always transpile the source code into es5 and export
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
[MIT](LICENSE)
|
||||
|
||||
@@ -10,7 +10,7 @@ $ cd socket.io
|
||||
$ npm install
|
||||
$ cd examples/chat
|
||||
$ npm install
|
||||
$ node .
|
||||
$ npm start
|
||||
```
|
||||
|
||||
And point your browser to `http://localhost:3000`. Optionally, specify
|
||||
|
||||
@@ -8,5 +8,8 @@
|
||||
"license": "BSD",
|
||||
"dependencies": {
|
||||
"express": "4.13.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,4 +263,20 @@ $(function() {
|
||||
socket.on('stop typing', function (data) {
|
||||
removeChatTyping(data);
|
||||
});
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
log('you have been disconnected');
|
||||
});
|
||||
|
||||
socket.on('reconnect', function () {
|
||||
log('you have been reconnected');
|
||||
if (username) {
|
||||
socket.emit('add user', username);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('reconnect_error', function () {
|
||||
log('attempt to reconnect has failed');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -191,7 +191,9 @@ Client.prototype.ondecoded = function(packet) {
|
||||
} else {
|
||||
var socket = this.nsps[packet.nsp];
|
||||
if (socket) {
|
||||
socket.onpacket(packet);
|
||||
process.nextTick(function() {
|
||||
socket.onpacket(packet);
|
||||
});
|
||||
} else {
|
||||
debug('no socket for namespace %s', packet.nsp);
|
||||
}
|
||||
|
||||
92
lib/index.js
92
lib/index.js
@@ -9,6 +9,7 @@ var engine = require('engine.io');
|
||||
var client = require('socket.io-client');
|
||||
var clientVersion = require('socket.io-client/package').version;
|
||||
var Client = require('./client');
|
||||
var Emitter = require('events').EventEmitter;
|
||||
var Namespace = require('./namespace');
|
||||
var Adapter = require('socket.io-adapter');
|
||||
var debug = require('debug')('socket.io:server');
|
||||
@@ -24,13 +25,14 @@ module.exports = Server;
|
||||
* Socket.IO client source.
|
||||
*/
|
||||
|
||||
var clientSource = read(require.resolve('socket.io-client/socket.io.js'), 'utf-8');
|
||||
var clientSource = undefined;
|
||||
var clientSourceMap = undefined;
|
||||
|
||||
/**
|
||||
* Server constructor.
|
||||
*
|
||||
* @param {http.Server|Number|Object} srv http server, port or options
|
||||
* @param {Object} opts
|
||||
* @param {Object} [opts]
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -94,6 +96,16 @@ Server.prototype.checkRequest = function(req, fn) {
|
||||
Server.prototype.serveClient = function(v){
|
||||
if (!arguments.length) return this._serveClient;
|
||||
this._serveClient = v;
|
||||
|
||||
if (v && !clientSource) {
|
||||
clientSource = read(require.resolve('socket.io-client/dist/socket.io.min.js'), 'utf-8');
|
||||
try {
|
||||
clientSourceMap = read(require.resolve('socket.io-client/dist/socket.io.js.map'), 'utf-8');
|
||||
} catch(err) {
|
||||
debug('could not load sourcemap file');
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -109,7 +121,7 @@ var oldSettings = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Backwards compatiblity.
|
||||
* Backwards compatibility.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
@@ -249,11 +261,14 @@ Server.prototype.attach = function(srv, opts){
|
||||
Server.prototype.attachServe = function(srv){
|
||||
debug('attaching client serving req handler');
|
||||
var url = this._path + '/socket.io.js';
|
||||
var urlMap = this._path + '/socket.io.js.map';
|
||||
var evs = srv.listeners('request').slice(0);
|
||||
var self = this;
|
||||
srv.removeAllListeners('request');
|
||||
srv.on('request', function(req, res) {
|
||||
if (0 === req.url.indexOf(url)) {
|
||||
if (0 === req.url.indexOf(urlMap)) {
|
||||
self.serveMap(req, res);
|
||||
} else if (0 === req.url.indexOf(url)) {
|
||||
self.serve(req, res);
|
||||
} else {
|
||||
for (var i = 0; i < evs.length; i++) {
|
||||
@@ -272,9 +287,13 @@ Server.prototype.attachServe = function(srv){
|
||||
*/
|
||||
|
||||
Server.prototype.serve = function(req, res){
|
||||
// Per the standard, ETags must be quoted:
|
||||
// https://tools.ietf.org/html/rfc7232#section-2.3
|
||||
var expectedEtag = '"' + clientVersion + '"';
|
||||
|
||||
var etag = req.headers['if-none-match'];
|
||||
if (etag) {
|
||||
if (clientVersion == etag) {
|
||||
if (expectedEtag == etag) {
|
||||
debug('serve client 304');
|
||||
res.writeHead(304);
|
||||
res.end();
|
||||
@@ -284,11 +303,42 @@ Server.prototype.serve = function(req, res){
|
||||
|
||||
debug('serve client source');
|
||||
res.setHeader('Content-Type', 'application/javascript');
|
||||
res.setHeader('ETag', clientVersion);
|
||||
res.setHeader('ETag', expectedEtag);
|
||||
res.setHeader('X-SourceMap', 'socket.io.js.map');
|
||||
res.writeHead(200);
|
||||
res.end(clientSource);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a request serving `/socket.io.js.map`
|
||||
*
|
||||
* @param {http.Request} req
|
||||
* @param {http.Response} res
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Server.prototype.serveMap = function(req, res){
|
||||
// Per the standard, ETags must be quoted:
|
||||
// https://tools.ietf.org/html/rfc7232#section-2.3
|
||||
var expectedEtag = '"' + clientVersion + '"';
|
||||
|
||||
var etag = req.headers['if-none-match'];
|
||||
if (etag) {
|
||||
if (expectedEtag == etag) {
|
||||
debug('serve client 304');
|
||||
res.writeHead(304);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
debug('serve client sourcemap');
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.setHeader('ETag', expectedEtag);
|
||||
res.writeHead(200);
|
||||
res.end(clientSourceMap);
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds socket.io to an engine.io instance.
|
||||
*
|
||||
@@ -322,7 +372,7 @@ Server.prototype.onconnection = function(conn){
|
||||
* Looks up a namespace.
|
||||
*
|
||||
* @param {String} name nsp name
|
||||
* @param {Function} fn optional, nsp `connection` ev handler
|
||||
* @param {Function} [fn] optional, nsp `connection` ev handler
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -342,10 +392,11 @@ Server.prototype.of = function(name, fn){
|
||||
/**
|
||||
* Closes server connection
|
||||
*
|
||||
* @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Server.prototype.close = function(){
|
||||
Server.prototype.close = function(fn){
|
||||
for (var id in this.nsps['/'].sockets) {
|
||||
if (this.nsps['/'].sockets.hasOwnProperty(id)) {
|
||||
this.nsps['/'].sockets[id].onclose();
|
||||
@@ -354,8 +405,10 @@ Server.prototype.close = function(){
|
||||
|
||||
this.engine.close();
|
||||
|
||||
if(this.httpServer){
|
||||
this.httpServer.close();
|
||||
if (this.httpServer) {
|
||||
this.httpServer.close(fn);
|
||||
} else {
|
||||
fn && fn();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -363,18 +416,23 @@ Server.prototype.close = function(){
|
||||
* Expose main namespace (/).
|
||||
*/
|
||||
|
||||
['on', 'to', 'in', 'use', 'emit', 'send', 'write', 'clients', 'compress'].forEach(function(fn){
|
||||
var emitterMethods = Object.keys(Emitter.prototype).filter(function(key){
|
||||
return typeof Emitter.prototype[key] === 'function';
|
||||
});
|
||||
|
||||
emitterMethods.concat(['to', 'in', 'use', 'send', 'write', 'clients', 'compress']).forEach(function(fn){
|
||||
Server.prototype[fn] = function(){
|
||||
var nsp = this.sockets[fn];
|
||||
return nsp.apply(this.sockets, arguments);
|
||||
return this.sockets[fn].apply(this.sockets, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
Namespace.flags.forEach(function(flag){
|
||||
Server.prototype.__defineGetter__(flag, function(){
|
||||
this.sockets.flags = this.sockets.flags || {};
|
||||
this.sockets.flags[flag] = true;
|
||||
return this;
|
||||
Object.defineProperty(Server.prototype, flag, {
|
||||
get: function() {
|
||||
this.sockets.flags = this.sockets.flags || {};
|
||||
this.sockets.flags[flag] = true;
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ exports.events = [
|
||||
|
||||
exports.flags = [
|
||||
'json',
|
||||
'volatile'
|
||||
'volatile',
|
||||
'local'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -69,10 +70,12 @@ Namespace.prototype.__proto__ = Emitter.prototype;
|
||||
*/
|
||||
|
||||
exports.flags.forEach(function(flag){
|
||||
Namespace.prototype.__defineGetter__(flag, function(){
|
||||
this.flags = this.flags || {};
|
||||
this.flags[flag] = true;
|
||||
return this;
|
||||
Object.defineProperty(Namespace.prototype, flag, {
|
||||
get: function() {
|
||||
this.flags = this.flags || {};
|
||||
this.flags[flag] = true;
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -137,7 +140,7 @@ Namespace.prototype.run = function(socket, fn){
|
||||
*/
|
||||
|
||||
Namespace.prototype.to =
|
||||
Namespace.prototype['in'] = function(name){
|
||||
Namespace.prototype.in = function(name){
|
||||
this.rooms = this.rooms || [];
|
||||
if (!~this.rooms.indexOf(name)) this.rooms.push(name);
|
||||
return this;
|
||||
|
||||
@@ -8,6 +8,7 @@ var parser = require('socket.io-parser');
|
||||
var url = require('url');
|
||||
var debug = require('debug')('socket.io:socket');
|
||||
var hasBin = require('has-binary');
|
||||
var assign = require('object-assign');
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
@@ -68,6 +69,7 @@ function Socket(nsp, client, query){
|
||||
this.connected = true;
|
||||
this.disconnected = false;
|
||||
this.handshake = this.buildHandshake(query);
|
||||
this.fns = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,10 +83,12 @@ Socket.prototype.__proto__ = Emitter.prototype;
|
||||
*/
|
||||
|
||||
flags.forEach(function(flag){
|
||||
Socket.prototype.__defineGetter__(flag, function(){
|
||||
this.flags = this.flags || {};
|
||||
this.flags[flag] = true;
|
||||
return this;
|
||||
Object.defineProperty(Socket.prototype, flag, {
|
||||
get: function() {
|
||||
this.flags = this.flags || {};
|
||||
this.flags[flag] = true;
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,8 +98,10 @@ flags.forEach(function(flag){
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.__defineGetter__('request', function(){
|
||||
return this.conn.request;
|
||||
Object.defineProperty(Socket.prototype, 'request', {
|
||||
get: function() {
|
||||
return this.conn.request;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -109,13 +115,7 @@ Socket.prototype.buildHandshake = function(query){
|
||||
function buildQuery(){
|
||||
var requestQuery = url.parse(self.request.url, true).query;
|
||||
//if socket-specific query exist, replace query strings in requestQuery
|
||||
if(query){
|
||||
query.t = requestQuery.t;
|
||||
query.EIO = requestQuery.EIO;
|
||||
query.transport = requestQuery.transport;
|
||||
return query;
|
||||
}
|
||||
return requestQuery || {};
|
||||
return assign({}, query, requestQuery);
|
||||
}
|
||||
return {
|
||||
headers: this.request.headers,
|
||||
@@ -281,8 +281,10 @@ Socket.prototype.leaveAll = function(){
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by `Namespace` upon succesful
|
||||
* Called by `Namespace` upon successful
|
||||
* middleware execution (ie: authorization).
|
||||
* Socket is added to namespace array before
|
||||
* call to join, so adapters can access it.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
@@ -345,7 +347,7 @@ Socket.prototype.onevent = function(packet){
|
||||
args.push(this.ack(packet.id));
|
||||
}
|
||||
|
||||
emit.apply(this, args);
|
||||
this.dispatch(args);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -482,3 +484,63 @@ Socket.prototype.compress = function(compress){
|
||||
this.flags.compress = compress;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch incoming event to socket listeners.
|
||||
*
|
||||
* @param {Array} event that will get emitted
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Socket.prototype.dispatch = function(event){
|
||||
debug('dispatching an event %j', event);
|
||||
var self = this;
|
||||
this.run(event, function(err){
|
||||
process.nextTick(function(){
|
||||
if (err) {
|
||||
return self.error(err.data || err.message);
|
||||
}
|
||||
emit.apply(self, event);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up socket middleware.
|
||||
*
|
||||
* @param {Function} middleware function (event, next)
|
||||
* @return {Socket} self
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Socket.prototype.use = function(fn){
|
||||
this.fns.push(fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes the middleware for an incoming event.
|
||||
*
|
||||
* @param {Array} event that will get emitted
|
||||
* @param {Function} last fn call in the middleware
|
||||
* @api private
|
||||
*/
|
||||
Socket.prototype.run = function(event, fn){
|
||||
var fns = this.fns.slice(0);
|
||||
if (!fns.length) return fn(null);
|
||||
|
||||
function run(i){
|
||||
fns[i](event, function(err){
|
||||
// upon error, short-circuit
|
||||
if (err) return fn(err);
|
||||
|
||||
// if no middleware left, summon callback
|
||||
if (!fns[i + 1]) return fn(null);
|
||||
|
||||
// go on to next
|
||||
run(i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
run(0);
|
||||
};
|
||||
|
||||
13
package.json
13
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "socket.io",
|
||||
"version": "1.5.0",
|
||||
"version": "1.7.3",
|
||||
"description": "node.js realtime framework server",
|
||||
"keywords": [
|
||||
"realtime",
|
||||
@@ -24,12 +24,13 @@
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"engine.io": "1.7.0",
|
||||
"socket.io-parser": "2.2.6",
|
||||
"socket.io-client": "1.5.0",
|
||||
"socket.io-adapter": "0.4.0",
|
||||
"debug": "2.3.3",
|
||||
"engine.io": "1.8.3",
|
||||
"has-binary": "0.1.7",
|
||||
"debug": "2.2.0"
|
||||
"object-assign": "4.1.0",
|
||||
"socket.io-adapter": "0.5.0",
|
||||
"socket.io-client": "1.7.3",
|
||||
"socket.io-parser": "2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-preset-es2015": "6.3.13",
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('socket.io', function(){
|
||||
if (err) return done(err);
|
||||
var ctype = res.headers['content-type'];
|
||||
expect(ctype).to.be('application/javascript');
|
||||
expect(res.headers.etag).to.be(clientVersion);
|
||||
expect(res.headers.etag).to.be('"' + clientVersion + '"');
|
||||
expect(res.text).to.match(/engine\.io/);
|
||||
expect(res.status).to.be(200);
|
||||
done();
|
||||
@@ -179,7 +179,7 @@ describe('socket.io', function(){
|
||||
io(srv);
|
||||
request(srv)
|
||||
.get('/socket.io/socket.io.js')
|
||||
.set('If-None-Match', clientVersion)
|
||||
.set('If-None-Match', '"' + clientVersion + '"')
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
expect(res.statusCode).to.be(304);
|
||||
@@ -399,7 +399,7 @@ describe('socket.io', function(){
|
||||
var net = require('net');
|
||||
var server = net.createServer();
|
||||
|
||||
var clientSocket = ioc('ws://0.0.0.0:' + PORT);
|
||||
var clientSocket = ioc('ws://0.0.0.0:' + PORT, { reconnection: false });
|
||||
|
||||
clientSocket.on('disconnect', function init() {
|
||||
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(0);
|
||||
@@ -1546,9 +1546,7 @@ describe('socket.io', function(){
|
||||
var srv = http();
|
||||
var sio = io(srv);
|
||||
srv.listen(function() {
|
||||
var addr = srv.listen().address();
|
||||
var url = 'ws://localhost:' + addr.port + '?key1=1&key2=2';
|
||||
var socket = ioc(url);
|
||||
var socket = client(srv, {query: {key1: 1, key2: 2}});
|
||||
sio.on('connection', function(s) {
|
||||
var parsed = require('url').parse(s.request.url);
|
||||
var query = require('querystring').parse(parsed.query);
|
||||
@@ -1562,10 +1560,8 @@ describe('socket.io', function(){
|
||||
it('should see query parameters sent from secondary namespace connections in handshake object', function(done){
|
||||
var srv = http();
|
||||
var sio = io(srv);
|
||||
var addr = srv.listen().address();
|
||||
var url = 'ws://localhost:' + addr.port;
|
||||
var client1 = ioc(url);
|
||||
var client2 = ioc(url + '/connection2', {query: {key1: 'aa', key2: '&=bb'}});
|
||||
var client1 = client(srv);
|
||||
var client2 = client(srv, '/connection2', {query: {key1: 'aa', key2: '&=bb'}});
|
||||
sio.on('connection', function(s){
|
||||
});
|
||||
sio.of('/connection2').on('connection', function(s){
|
||||
@@ -1647,11 +1643,10 @@ describe('socket.io', function(){
|
||||
var clientSocket = client(srv, { reconnectionAttempts: 10, reconnectionDelay: 100 });
|
||||
clientSocket.once('connect', function(){
|
||||
srv.close(function(){
|
||||
srv.listen(port, function(){
|
||||
clientSocket.on('reconnect', function(){
|
||||
clientSocket.emit('ev', 'payload');
|
||||
});
|
||||
clientSocket.on('reconnect', function(){
|
||||
clientSocket.emit('ev', 'payload');
|
||||
});
|
||||
sio.listen(port);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2237,4 +2232,97 @@ describe('socket.io', function(){
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('socket middleware', function(done){
|
||||
var Socket = require('../lib/socket');
|
||||
|
||||
it('should call functions', function(done){
|
||||
var srv = http();
|
||||
var sio = io(srv);
|
||||
var run = 0;
|
||||
|
||||
srv.listen(function(){
|
||||
var socket = client(srv, { multiplex: false });
|
||||
|
||||
socket.emit('join', 'woot');
|
||||
|
||||
sio.on('connection', function(socket){
|
||||
socket.use(function(event, next){
|
||||
expect(event).to.eql(['join', 'woot']);
|
||||
event.unshift('wrap');
|
||||
run++;
|
||||
next();
|
||||
});
|
||||
socket.use(function(event, next){
|
||||
expect(event).to.eql(['wrap', 'join', 'woot']);
|
||||
run++;
|
||||
next();
|
||||
});
|
||||
socket.on('wrap', function(data1, data2){
|
||||
expect(data1).to.be('join');
|
||||
expect(data2).to.be('woot');
|
||||
expect(run).to.be(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass errors', function(done){
|
||||
var srv = http();
|
||||
var sio = io(srv);
|
||||
|
||||
srv.listen(function(){
|
||||
var clientSocket = client(srv, { multiplex: false });
|
||||
|
||||
clientSocket.emit('join', 'woot');
|
||||
|
||||
clientSocket.on('error', function(err){
|
||||
expect(err).to.be('Authentication error');
|
||||
done();
|
||||
});
|
||||
|
||||
sio.on('connection', function(socket){
|
||||
socket.use(function(event, next){
|
||||
next(new Error('Authentication error'));
|
||||
});
|
||||
socket.use(function(event, next){
|
||||
done(new Error('nope'));
|
||||
});
|
||||
|
||||
socket.on('join', function(){
|
||||
done(new Error('nope'));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass `data` of error object', function(done){
|
||||
var srv = http();
|
||||
var sio = io(srv);
|
||||
|
||||
srv.listen(function(){
|
||||
var clientSocket = client(srv, { multiplex: false });
|
||||
|
||||
clientSocket.emit('join', 'woot');
|
||||
|
||||
clientSocket.on('error', function(err){
|
||||
expect(err).to.eql({ a: 'b', c: 3 });
|
||||
done();
|
||||
});
|
||||
|
||||
sio.on('connection', function(socket){
|
||||
socket.use(function(event, next){
|
||||
var err = new Error('Authentication error');
|
||||
err.data = { a: 'b', c: 3 };
|
||||
next(err);
|
||||
});
|
||||
|
||||
socket.on('join', function(){
|
||||
done(new Error('nope'));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user