Compare commits

...

233 Commits
1.3.4 ... 1.6.0

Author SHA1 Message Date
Damien Arrachequesne
57b386385e [chore] Release 1.6.0 (#2757) 2016-11-20 04:26:56 +01:00
Damien Arrachequesne
9e7567daee [chore] Bump socket.io-adapter to version 0.5.0 (#2756) 2016-11-20 03:51:57 +01:00
Damien Arrachequesne
2e36799b17 [chore] Bump engine.io to version 1.8.0 (#2755) 2016-11-20 03:50:32 +01:00
Damien Arrachequesne
9bb5e9de2f [chore] Bump debug to version 2.3.3 (#2754) 2016-11-20 03:42:09 +01:00
Luca Tabone
ff2c15de68 [perf] Minor code optimizations (#2219) 2016-11-18 02:03:06 +01:00
Damien Arrachequesne
a483658607 [example] Add disconnection/reconnection logs to the chat example (#2675) 2016-11-18 01:52:45 +01:00
Julian Grinblat
4c5dbd8824 [fix] Don't drop query variables on handshake (#2745)
Parameters passed during handshake, such as tokens, were being dropped.
2016-11-16 01:17:19 +01:00
mhmeadows63
e14a10b7ce [feature] add support for Server#close(callback) (#2748) 2016-11-15 21:52:56 +01:00
Alex
5a123beea5 [feature] Add support for socket middleware (#2306) 2016-11-05 01:51:29 +01:00
Philip YoonShin
2ed5f0f5fb [chore] Update year to 2016 (#2456) 2016-11-05 01:19:15 +01:00
Julian Grinblat
e9f980c475 [feature] Add support for all event emitter methods (#2601) 2016-11-05 01:14:21 +01:00
Jamie Davis
6f44f3a8ef [test] Fix leaking clientSocket (#2721)
Test 'should be able to close sio sending a port' defined a clientSocket
but didn't set 'reconnection: false'.

Now, the default behavior of a clientSocket is 'reconnection: true'.
As a result, the clientSocket was "leaked" from the test case
and seemed to intermittently connect to the servers in subsequent
test cases. This would cause other tests to timeout unexpectedly.

It's not clear to me why this would happen, since the test case
assigns a unique port number to the socket.
However, if you go into socket.io-client and assign and log
unique IDs to each socket, then you'll see that this clientSocket
shows up in other test cases if the reconnectionDelay strikes
unluckily.
2016-11-05 01:06:04 +01:00
Atanas Palavrov
04fc0f3677 [feature] Loading client script on demand. (#2567)
Support for the serving of the client script mess with packagers like
browserify, webpack. Especcialy in projects where it is not used at all.
This patch is workaround to avoid that problem in the cases when client
script is not served.
2016-10-30 14:22:00 +01:00
Kenton Varda
d026c00d05 [fix] Make ETag header comply with standard. (#2603)
The standard says that an ETag must be surrounded in double quotes:

https://tools.ietf.org/html/rfc7232#section-2.3

Although browsers tend to be lenient, omitting the quotes can confuse/break some kinds of proxies and other tools that demand compliant formatting. For example, Sandstorm.io enforces strict HTTP usage for security reasons and will block responses with invalid ETags.
2016-10-30 14:19:00 +01:00
Damien Arrachequesne
fdf64cc38f [chore] Release 1.5.1 (#2735) 2016-10-24 03:31:32 +02:00
Damien Arrachequesne
5badb6436e [chore] Bump socket.io-parser to 2.3.1 (#2734) 2016-10-24 03:23:03 +02:00
Damien Arrachequesne
c20e0b26c9 [chore] Bump engine.io to 1.7.2 (#2729) 2016-10-24 03:21:11 +02:00
bananaapple
5c10c5439b [test] Use client function to unify client in test script (#2731) 2016-10-24 02:35:01 +02:00
Damien Arrachequesne
8182ecc61c [chore] Add Github issue and PR templates (#2733) 2016-10-22 09:19:08 +02:00
Feram Bot
ccd3376627 [docs] Minor fixes (#2526) 2016-10-21 03:21:45 +02:00
Damien Arrachequesne
58a73d39e9 [chore] Bump socket.io-parser to 2.3.0 (#2730) 2016-10-21 03:18:49 +02:00
Tom Atkinson
e60bd5a4da [fix] Avoid swallowing exceptions thrown by user event handlers (#2682) 2016-10-21 03:16:36 +02:00
Paul Meinhardt
21dffa4b58 [docs] Link readme npm package badge to npm registry page (#2612) 2016-10-21 03:10:33 +02:00
Marcio Puga
94852e3d23 [docs] Fix typo (#2724) 2016-10-21 03:06:59 +02:00
davidlondono
b8c60506a6 [docs] Fix JSDoc of optional parameters (#2465)
Making proper optional Docs for socketIO
2016-10-21 03:02:59 +02:00
syuilo⭐️
ecc76f48bc [docs] Add link to LICENSE (#2221) 2016-10-21 03:00:38 +02:00
Damien Arrachequesne
c94058f9b0 [chore] release 1.5.0 (#2711) 2016-10-07 00:13:33 +02:00
Damien Arrachequesne
43d9a4b55d [feature] Add a 'disconnecting' event to access to socket.rooms upon disconnection (#2332) 2016-10-06 23:23:26 +02:00
Alejandro Oviedo
df916172dd [chore] Link build badge to master branch (#2549) 2016-10-06 23:12:15 +02:00
Damien Arrachequesne
271c625243 [chore] Restrict files included in npm package (#2709) 2016-10-06 23:11:33 +02:00
Damien Arrachequesne
628fe8f1b2 [chore] Point towards current master of socket.io-client (#2710) 2016-10-06 23:10:54 +02:00
Damien Arrachequesne
db62e1bf67 [chore] Remove unused zuul-ngrok dependency (#2708) 2016-10-06 23:10:33 +02:00
YasharF
ba4c7921ef [chore] Bump engine.io to 1.7.0 (#2707) 2016-10-06 10:03:55 +02:00
Damien Arrachequesne
30ea0b8d7d Merge pull request #2599 from boazsegev/patch-1
Documentation update to help new programmers
2016-08-05 21:07:30 +02:00
Bo
2d141aff7c Prevent mixup for new programmers
The documentation, inadvertently, causes confusion for newer programmers, hindering their learning curve and ability to learn `socket.io` faster.

This proposed change aims at preventing this confusion to allow new programmers easier access to resources, especially when searching the web for more information.

The name `socket` in the documentation refers to the API gateway, or abstraction layer, related to the `client` and other properties. However, in the rest of the programming world, `sockets` usually refer to Berklee sockets or the lower-level communication channel that is used to implement Protocols such as the Websocket Protocol and HTTP.

New programmers often search for more informations using the `sockets` keyword when they are grappling with learning the `socket.io` API.

A good example is the stack overflow site, where newer programmers incorrectly tag their questions `sockets` and in turn don't get a fast response to their questions.

By simply changing the name of the variable used to describe socket.io's "Socket" class instances from `socket` to `client`, this mixup should be mitigated considerably.
2016-06-26 14:32:37 -04:00
Guillermo Rauch
40763d3962 1.4.8 2016-06-23 19:24:38 -07:00
Guillermo Rauch
2a092bd2fb Release 1.4.8 2016-06-23 19:22:41 -07:00
Guillermo Rauch
4137eb5c43 package: bump engine.io 2016-06-23 19:12:28 -07:00
Guillermo Rauch
e3207005da 1.4.7 2016-06-23 17:31:33 -07:00
Guillermo Rauch
42aa77614e Release 1.4.7 2016-06-23 17:25:46 -07:00
Guillermo Rauch
1491a96c95 package: bump engine.io 2016-06-23 17:11:15 -07:00
Guillermo Rauch
dcca01f5a4 Release 1.4.6 2016-05-02 20:57:44 -07:00
Guillermo Rauch
3b58fa04d5 package: bump engine.io 2016-05-02 20:56:15 -07:00
Naoyuki Kanezawa
0c6d50d9c0 Merge pull request #2416 from nus-fboa2016-si/chatexample
updated express version to express 4
2016-04-12 03:58:08 +09:00
Naoyuki Kanezawa
881f16553c Merge pull request #2508 from tw0517tw/quote-exec
add quote to exec paths, prevent error when spaces in path
2016-04-12 03:57:43 +09:00
Guillermo Rauch
e5a8d4d2d9 Merge pull request #2520 from nkzawa/fix/ignore-dist
Ignore dist directory for now
2016-04-11 08:45:11 -07:00
Guillermo Rauch
fb0253edea Merge pull request #2422 from nus-fboa2016-si/queryStringFix
Fix for Issue #331 on socket.io-client
2016-04-11 08:44:59 -07:00
tw0517tw
3c5f5a0864 use a bigger timeout for slower machine 2016-04-11 22:31:47 +08:00
tw0517tw
a23d26a617 add quote to exec paths, prevent error when spaces in path 2016-04-11 22:21:34 +08:00
Zhu Liang
910b5d77a6 fixed version notation 2016-04-11 22:19:49 +08:00
Naoyuki Kanezawa
438ad63cdf Merge pull request #2420 from revington/test-node-v5-stable
[Travis] Add Node 5.x (Stable) to the test matrix
2016-04-11 23:09:41 +09:00
Naoyuki Kanezawa
7e9a67d8ee Merge pull request #2415 from nus-fboa2016-si/documentation
Documentation
2016-04-11 23:05:33 +09:00
Naoyuki Kanezawa
0ae070885d Merge pull request #2477 from callahad/chat-layout-fix
Fix chat display in Firefox
2016-04-11 23:00:07 +09:00
Naoyuki Kanezawa
36d99d8d84 Merge pull request #2492 from westy92/master
Update package.json
2016-04-11 22:20:46 +09:00
nkzawa
0e63b0910e ignore dist for now 2016-04-11 22:11:19 +09:00
Guillermo Rauch
3c7350fa58 Merge pull request #2509 from tw0517tw/patch-1
stop prepend /# before id when no namespace
2016-04-10 11:24:42 -07:00
Guillermo Rauch
aadd5da655 Merge pull request #2496 from nus-fboa2016-si/compat-test
Added test for compat version transformed by babel
2016-04-02 18:31:30 -07:00
吳東曄 Wu, Dung-Ie
6d4128750b stop append /# before id when no namespace 2016-04-02 01:55:53 +08:00
Zhu Liang
6edcd1c6ba styling fixes 2016-03-31 12:55:42 +08:00
Zhu Liang
6b2394e612 disable loading lib by default to avoid syntax error due to lib containing new es6 syntax 2016-03-31 03:54:32 +08:00
Zhu Liang
677af3fa11 changed env var name, added testing documentation to readme 2016-03-21 13:11:03 +08:00
Zhu Liang
a1ff739b36 babel transpile before test, print error 2016-03-19 20:19:08 +08:00
Zhu Liang
de5b588e17 explicit distinction between current and compat in test so we can serve either compat or current as default 2016-03-19 20:13:57 +08:00
Zhu Liang
5a20c1195b set env vars in travis 2016-03-19 19:49:41 +08:00
Zhu Liang
5253bc400b use multiple npm scripts 2016-03-19 19:41:14 +08:00
Zhu Liang
1245a5639e added compat test 2016-03-19 19:21:54 +08:00
Zhu Liang
88161539a1 implement compat test using env variable 2016-03-17 13:42:29 +08:00
Zhu Liang
d99d4d15ae add compat test for babel-transformed codes 2016-03-17 13:11:20 +08:00
Seth Westphal
06ecfe5444 Explicit local gulp is unnecesary 2016-03-16 13:01:49 -05:00
Seth Westphal
e90b4eba1e Update repository URL 2016-03-16 12:58:59 -05:00
Guillermo Rauch
c7de1a1adf Merge pull request #2471 from nus-fboa2016-si/gulp-rebased
Add gulp and babel
2016-03-12 20:04:48 -08:00
Dan Callahan
7bae6ac636 Fix chat display in Firefox 2016-03-08 19:50:55 -06:00
Diga Widyaprana
355b5156fe Remove node 0.8 from travis 2016-03-09 09:36:51 +08:00
Diga Widyaprana
3e168ee0b8 Redirect make tasks to gulp 2016-03-06 11:40:57 +08:00
Diga Widyaprana
ed9ab77dcb Minor fixes to gulp tasks
- Only provide entry point as first argument of gulp.src
- {read:false} option for mocha tests
- change timeout:2000 to slow:200 to mirror makefile's mocha options
- replace var with const where appropriate
2016-03-06 11:40:57 +08:00
Diga Widyaprana
1104cd135e Use local instead of global gulp in npm test 2016-03-06 11:40:57 +08:00
Diga Widyaprana
0be915cd0f Add gulp task clean to clean transpile output
- Work done by @YijinL. Part of @05ad308
2016-03-06 11:40:57 +08:00
Diga Widyaprana
c6dd41b915 Minor refactoring to transpile task
- Transpiling is now gulp transpile
- Default redirects to transpile
- Refactor transpile output directory to a separate constant
- Work by @YijinL in @05ad308
2016-03-06 11:32:40 +08:00
Diga Widyaprana
0f14312d7b Add gulp help
Work was done by @YijinL in 2 separate commits (@9204125 and @05ad308)
2016-03-06 11:32:09 +08:00
Diga Widyaprana
97bd95f036 Don't use dynamic dependencies 2016-03-04 18:06:00 +08:00
Diga Widyaprana
11e0f19272 Inline babel configuration 2016-03-04 18:06:00 +08:00
Yijin
e388a3319d npm test script to use gulp 2016-03-04 18:06:00 +08:00
Zheng Weihan
b551ce9835 added test-cov task. 2016-03-04 18:06:00 +08:00
Zhu Liang
0bac96a6b2 added comment for babel 2016-03-04 14:46:08 +08:00
Zhu Liang
1d07b10339 integrated babel into gulp 2016-03-04 14:46:08 +08:00
Zheng Weihan
398b5479f0 delete unused dependency 2016-03-04 14:45:55 +08:00
Zheng Weihan
d9eb729eab implement gulp build system for test. 2016-03-04 14:45:03 +08:00
whattokingu
f9db72997f Merge pull request #10 from whattokingu/queryStringFix
Query string fix
2016-02-14 13:57:06 +08:00
Zheng Weihan
1293505dc2 update tests. 2016-02-14 13:48:28 +08:00
Zheng Weihan
f4e9e71c56 Merge branch 'queryStringFix' of https://github.com/whattokingu/socket.io into queryStringFix
# By whattokingu
# Via whattokingu
* 'queryStringFix' of https://github.com/whattokingu/socket.io:
  conform to style guide

Conflicts:
	lib/client.js
2016-02-14 13:47:59 +08:00
Zheng Weihan
045674de97 remove unnecessary decoder. url.parse already decodes string.
add test to test decoding function.
2016-02-14 13:46:26 +08:00
whattokingu
7091acf24c Merge pull request #9 from whattokingu/queryStringFix
Query string fix
2016-02-13 14:41:15 +08:00
whattokingu
19341051e8 conform to style guide 2016-02-13 14:35:12 +08:00
Zheng Weihan
e141e09aaf change decodeUriComponents calls 2016-02-13 14:28:21 +08:00
Zheng Weihan
5fabe4e780 call decodeURIComponent on query received from client.
update package.son to point to latest commit in socket.o-client package (with URI encoder)
2016-02-13 14:10:20 +08:00
whattokingu
7760a71d90 Merge pull request #8 from whattokingu/queryStringFix
add comments to code
2016-02-04 13:28:29 +08:00
Zheng Weihan
c077357eff add comments to code 2016-02-04 13:27:36 +08:00
whattokingu
2f26a2bdb4 Merge pull request #7 from whattokingu/queryStringFix
add test for issue #331 on socket.io-client.
2016-01-31 15:45:35 +08:00
Zheng Weihan
13af610f6d add test for issue #331 on socket.io-client. 2016-01-31 15:44:39 +08:00
whattokingu
abcedf53ec Merge pull request #6 from whattokingu/queryStringFix
sync to master branch
2016-01-31 11:23:02 +08:00
Zheng Weihan
24456fdcbe Merge branch 'master' into queryStringFix
* master:
  Release 1.4.5
  package: bump `engine.io`
  add a test for graceful shutdown
2016-01-31 11:21:30 +08:00
Pedro Narciso García Revington
25116ab179 test node 5 (stable) 2016-01-30 21:53:04 +01:00
Zhu Liang
a116d52e30 updated express version to express 4 2016-01-30 11:57:31 +08:00
whattokingu
cecf5f127e Merge pull request #5 from whattokingu/documentation
Added Documentation
2016-01-30 11:31:11 +08:00
Zheng Weihan
1c467e15e6 Issue #2400, added documentation 2016-01-30 11:28:40 +08:00
whattokingu
a110542563 Merge pull request #4 from whattokingu/queryStringFix
Fix for Issue #331 on socket.io-client
2016-01-30 10:16:19 +08:00
Zheng Weihan
7d55724468 refactor parsing of URL in CONNECT packet to use 'url' library. 2016-01-30 09:47:28 +08:00
Zheng Weihan
1d84c55743 fix to issue #331 on socket.o-client.
Parses CONNECT packet for query string and replaces query in socket.handshake.
2016-01-28 14:40:05 +08:00
Guillermo Rauch
b3fc530abe Release 1.4.5 2016-01-26 13:26:17 -08:00
Guillermo Rauch
d0dfa54dcb package: bump engine.io 2016-01-26 10:42:41 -08:00
Guillermo Rauch
198b836759 Merge pull request #2399 from nkzawa/graceful-close
Add a test for graceful shutdown
2016-01-21 09:15:36 -08:00
nkzawa
a75f46f06f add a test for graceful shutdown 2016-01-21 20:50:44 +09:00
Naoyuki Kanezawa
2a91fd57c7 Merge pull request #2344 from denghongcai/patch-2
fix wrong jsdoc
2016-01-17 15:25:32 +09:00
Naoyuki Kanezawa
fe891293b2 Merge pull request #2353 from faizalpribadi/patch-1
fix typo word :)
2016-01-17 15:23:35 +09:00
Naoyuki Kanezawa
6e450f75b4 Merge pull request #2374 from darrachequesne/patch-4
Add badges showing dependency status
2016-01-17 15:22:52 +09:00
Naoyuki Kanezawa
22c985cae6 Merge pull request #2380 from darrachequesne/patch-5
Document type change of Socket#rooms
2016-01-17 15:22:05 +09:00
Guillermo Rauch
fea3d79a2c Release 1.4.4 2016-01-10 22:36:31 -08:00
Guillermo Rauch
d3dde130b7 package: bump engine.io 2016-01-10 22:27:44 -08:00
Damien Arrachequesne
899de7f873 Document type change of Socket#rooms 2016-01-09 22:08:30 +01:00
Guillermo Rauch
f1a3e8db2a Release 1.4.3 2016-01-08 08:17:50 -08:00
Guillermo Rauch
dad82c3343 Release 1.4.2 2016-01-07 18:58:05 -08:00
Guillermo Rauch
a6cbf6b205 package: bump engine.io 2016-01-07 18:14:39 -08:00
Damien Arrachequesne
580100d491 Bump dev dependencies 2016-01-07 22:59:28 +01:00
Damien Arrachequesne
acb9cb421d Add badges showing dependency status 2016-01-07 22:58:59 +01:00
Guillermo Rauch
6d5d7e4411 Release 1.4.1 2016-01-07 12:52:27 -08:00
Guillermo Rauch
ddb3445f3d Release 1.4.0 2016-01-05 15:44:48 -08:00
Guillermo Rauch
6eb9807f17 package: bump engine.io for sec advisory 2016-01-05 13:40:54 -08:00
Faizal Pribadi
abe2394a24 fix typo word :)
update docs source code
2015-12-20 16:16:42 +07:00
Hongcai Deng
7012ba6c64 fix wrong jsdoc 2015-12-14 15:31:42 +08:00
Guillermo Rauch
7b0073c00f Merge pull request #2335 from nkzawa/patch-7
Improve the chat demo
2015-12-04 17:10:23 -08:00
nkzawa
0313ad0ea3 improve the chat demo 2015-12-05 10:07:08 +09:00
Guillermo Rauch
d310d42472 package: bump engine.io 2015-12-04 10:56:08 -08:00
Guillermo Rauch
709ceba00a package: bump socket.io-adapter for release 2015-12-03 10:28:33 -08:00
Guillermo Rauch
b29312bc61 package: bump engine.io for node 0.8 fix 2015-12-01 12:15:36 -08:00
Guillermo Rauch
51901160df package: temporarily revert version for tests 2015-12-01 11:24:06 -08:00
Guillermo Rauch
ab1b36e13f package: bump engine.io for ws memory fix 2015-11-30 08:16:21 -08:00
Guillermo Rauch
f7a2f35590 package: bump engine.io 2015-11-28 16:34:44 -08:00
Guillermo Rauch
c348737fe6 socket.io: increase large binary data test timeout 2015-11-28 15:13:13 -08:00
Guillermo Rauch
dde3737165 package: bump engine.io for release 2015-11-28 12:07:08 -08:00
Guillermo Rauch
8df4c7931b Merge pull request #2325 from darrachequesne/patch-2
Trigger callback even when joining an already joined room
2015-11-28 10:56:46 -08:00
Damien Arrachequesne
1dfacc6647 Trigger callback even when joining an already joined room 2015-11-27 22:08:18 +01:00
Guillermo Rauch
35a0fe0377 package: bump parser 2015-11-25 10:14:56 -08:00
Guillermo Rauch
3b00312fa7 namespace: clear rooms flag after a clients call (fixes #1978) 2015-11-23 09:40:57 -08:00
Guillermo Rauch
7b420295ef Merge pull request #2249 from pmq20/minqi-another
[Travis] Add Node 4.x to the test matrix
2015-11-23 09:31:48 -08:00
Guillermo Rauch
c504315982 Merge pull request #2322 from darrachequesne/issue-2199-clean
Add hasOwnProperty checks
2015-11-23 09:19:35 -08:00
Guillermo Rauch
520b5c37d5 Merge pull request #2321 from nkzawa/patch-6
Update redirects in README
2015-11-23 09:19:03 -08:00
Damien Arrachequesne
09f446eca0 Add hasOwnProperty checks 2015-11-23 15:12:21 +01:00
Naoyuki Kanezawa
aecf3bf71c Merge pull request #2218 from futbalguy/master
Clarified documentation of Socket.in
2015-11-23 17:37:07 +09:00
nkzawa
6c0a79e2b9 update redirects in README 2015-11-23 17:28:11 +09:00
Guillermo Rauch
8683206e31 Merge pull request #2239 from darrachequesne/issue-2199
converted arrays to objects
2015-11-22 10:34:57 -08:00
Guillermo Rauch
988d9d2346 Merge pull request #1999 from nkzawa/patch-3
Fix a few assertions are not executed properly
2015-11-22 10:17:02 -08:00
Damien Arrachequesne
b73d9bea4e converted arrays to objects 2015-11-22 11:12:40 +01:00
Naoyuki Kanezawa
d4fb6a5904 Merge pull request #2316 from tripu/master
Update “debug” to avoid vulnerability in “ms”
2015-11-22 10:39:23 +09:00
tripu
0517c609ba Avoid ^ in "debug" dependency (fixes #2314) 2015-11-21 23:59:16 +01:00
tripu
aa9438fee2 Update package "debug" to avoid "ms" vulnerability 2015-11-21 23:55:00 +01:00
Guillermo Rauch
aee466cc71 Update Readme.md 2015-11-21 10:54:19 -08:00
Guillermo Rauch
65f75d7732 Merge branch 'master' of github.com:socketio/socket.io 2015-11-21 10:46:26 -08:00
Guillermo Rauch
279c52a4c5 package: bump socket.io-parser 2015-11-21 10:45:43 -08:00
Naoyuki Kanezawa
67d1a67b1c Merge pull request #2319 from darrachequesne/patch-3
Minor fix
2015-11-21 23:21:39 +09:00
Damien Arrachequesne
aae68d74b1 Minor performance optimization 2015-11-20 22:03:03 +01:00
Damien Arrachequesne
bf5897cedc Fixed tests with large data 2015-11-20 22:01:16 +01:00
Damien Arrachequesne
a1a1c6657a Removed unused variable 2015-11-20 22:00:42 +01:00
Guillermo Rauch
2a4f7ae161 Merge pull request #2136 from nkzawa/patch-5
Don't set request property
2015-11-20 12:59:05 -08:00
Naoyuki Kanezawa
dba0576ca9 Merge pull request #2317 from ChaofengZhou/master
fixed a typo in the example code
2015-11-20 13:13:10 +09:00
Chaofeng
ba90f0991b fixed a typo in the example code 2015-11-19 21:09:34 -07:00
Guillermo Rauch
9a54e9cace package: bump mocha 2015-11-18 19:53:25 -08:00
Guillermo Rauch
9df4cb64b8 bump zuul-ngrok 2015-11-18 19:51:47 -08:00
Guillermo Rauch
c8f525868a package: bump has-binary 2015-11-18 16:56:06 -08:00
Guillermo Rauch
a39d7c2ae4 Merge pull request #2171 from KevinMartin/patch-1
Actually prevent double callbacks...
2015-11-18 12:56:01 -08:00
Guillermo Rauch
4ba266d404 Merge pull request #2307 from darrachequesne/patch-1
Upgrade npm version in order to fix node v0.8 build
2015-11-16 15:55:20 -08:00
Damien Arrachequesne
6b49779420 Upgrade npm version in order to fix node v0.8 build 2015-11-17 00:44:42 +01:00
Guillermo Rauch
b1775b1cb8 Merge pull request #2051 from tobalsgithub/master
Allowing a custom function for opts.allowRequest
2015-11-16 13:15:08 -08:00
Guillermo Rauch
ef52967301 Merge pull request #2271 from dazorni/master
Working travis build status
2015-11-16 13:12:26 -08:00
Guillermo Rauch
fde38b1bd7 Merge pull request #2208 from odeke-em/fix-legacy-repo-info
README: fixed up legacy repo links
2015-11-16 13:10:24 -08:00
Sebastian Zorn
75da57abb2 Working travis build status 2015-10-06 21:42:33 +02:00
Guillermo Rauch
21ea31a34e Merge branch '1.3.7-patch' 2015-09-21 04:30:59 +04:00
Guillermo Rauch
e2ebd4349b Release 1.3.7 2015-09-21 04:21:11 +04:00
Guillermo Rauch
b771f74a22 package: bump socket.io-client for node4 compatibility 2015-09-21 04:16:59 +04:00
Guillermo Rauch
8744007dc7 package: bump engine.io for node4 compatibility 2015-09-21 04:10:19 +04:00
P.S.V.R
3658928ee7 [Travis] Add Node 4.x to the test matrix 2015-09-16 17:39:26 +08:00
Guillermo Rauch
210e688732 package: bump engine.io 2015-09-09 15:47:14 -07:00
Guillermo Rauch
ae5420b727 package: bump engine.io and socket.io-client 2015-08-30 10:51:25 -07:00
futbalguy
d5b3bb46f8 Clarified documentation of Socket.in 2015-08-23 10:12:23 -07:00
Emmanuel Odeke
575d35a371 README: fixed up legacy repo links 2015-08-16 20:36:39 -06:00
Guillermo Rauch
e41483be9e Merge branch '1.3.6-patch' 2015-07-14 20:04:44 -07:00
Guillermo Rauch
c79e787671 test: better timeout for stress test 2015-07-14 19:58:42 -07:00
Guillermo Rauch
a2f6bb99d6 Merge branch '1.3.6-patch' 2015-07-14 18:02:56 -07:00
Guillermo Rauch
3e4061bfef Release 1.3.6 2015-07-14 17:59:50 -07:00
Guillermo Rauch
4c1d691fe5 package: bump engine.io to fix build on windows 2015-07-09 09:28:43 -07:00
Kevin Jose Martin
514aeb4fcd Actually prevent double callbacks...
We declare `sent = false` and even check `if (sent)` is truthy, but we never set it to truthy, therefore it never really *prevents double callbacks*...
2015-07-06 11:36:00 -04:00
Nathan Rajlich
876833198d Merge pull request #2111 from kemitchell/spdx-license
Use a Standard-Compliant License Identifier
2015-06-05 11:51:30 -07:00
Naoyuki Kanezawa
4d36d6c01a don't set request property 2015-05-30 03:34:05 +09:00
Guillermo Rauch
43fa075ec4 bump client 2015-05-27 22:56:15 -07:00
Guillermo Rauch
91c7bde34b Merge commit '342faf219793fc5c1f130fc33e3fb5422dab516d' 2015-05-27 22:55:15 -07:00
Guillermo Rauch
874a4a8535 package: bump client 2015-05-27 08:19:15 -07:00
Guillermo Rauch
93b571406e package: bump engine.io to fix build issues 2015-05-25 14:34:10 -07:00
Kyle Mitchell
98af793f07 use a valid SPDX license identifier 2015-05-05 00:08:44 +00:00
Guillermo Rauch
3f72dd3322 Merge pull request #2063 from kapouer/patch-1
Let adapter.add find connected socket
2015-04-10 21:38:41 -07:00
Guillermo Rauch
d0d38220fb Update Readme.md 2015-04-08 16:53:04 -07:00
Guillermo Rauch
f8aa157d5d remove proxy index file 2015-04-05 16:53:28 -07:00
Guillermo Rauch
0e13e9a268 bumped adapter 2015-04-05 15:52:59 -07:00
Guillermo Rauch
916872587f Merge pull request #2013 from nkzawa/namespace-flags
Supports flags on namespace
2015-04-05 15:51:54 -07:00
Guillermo Rauch
a7072845ea Merge pull request #2006 from nkzawa/patch-4
improve Socket#packet and Client#packet and enable volatile and compress when broadcast
2015-04-05 15:51:49 -07:00
Jérémy Lal
425409945b Let adapter.add find connected socket
When a socket connects, it joins its own room, resulting in a call to adapter.add.
The adapter in turn should be able to find the socket by id.
2015-03-24 14:54:52 +01:00
Guillermo Rauch
5826ef0bb5 Merge pull request #2059 from rase-/update/debug
Bump debug to 2.1.3
2015-03-17 16:42:00 -07:00
Tony Kovanen
14e32a9bad Bump debug to 2.1.3 2015-03-18 01:40:19 +02:00
TC
1dde0f3947 Allowing a custom function for opts.allowRequest 2015-03-12 15:50:31 -06:00
Guillermo Rauch
342faf2197 Release 1.3.5 2015-03-03 10:50:10 -08:00
Guillermo Rauch
12c6ee132d improve test 2015-03-03 10:34:56 -08:00
Guillermo Rauch
c9d909c993 package: bump socket.io-parser 2015-03-03 10:34:40 -08:00
Guillermo Rauch
125ab51338 test: added test for parser breakage 2015-03-03 10:08:26 -08:00
Guillermo Rauch
b31ac18554 test with 0.12 2015-02-19 15:38:35 -08:00
Naoyuki Kanezawa
53cdd8f1fc support flags on namespace 2015-02-20 03:34:09 +09:00
Naoyuki Kanezawa
81aea995ed improve Socket#packet and Client#packet 2015-02-15 04:33:20 +09:00
Naoyuki Kanezawa
56fe26661d fix a few assertions 2015-02-12 06:09:30 +09:00
Guillermo Rauch
a93d05a9f3 package: bump parser 2015-02-03 16:30:49 -08:00
Guillermo Rauch
5ce06d3088 socket: warn node_redis-style about missing error 2015-02-03 16:26:21 -08:00
Guillermo Rauch
816bfec783 added failing tests 2015-02-03 16:26:08 -08:00
Guillermo Rauch
0a17c90d7a test: added failing test 2015-02-03 15:10:46 -08:00
Guillermo Rauch
3645741b86 test: increase timeout for large binary data test 2015-01-31 09:35:37 -08:00
Guillermo Rauch
f2a7322b5a update deps 2015-01-31 08:46:32 -08:00
Guillermo Rauch
97c6568f65 Merge pull request #1966 from cha0s/clients
Suggestion for implementation of clients API
2015-01-31 08:34:43 -08:00
Ruben Rodriguez II
8814825a35 Suggestion for implementation of clients API 2015-01-31 02:17:49 -06:00
Guillermo Rauch
58eaecad27 Merge branch 'master' of github.com:Automattic/socket.io 2015-01-29 20:39:00 -08:00
Guillermo Rauch
94157e650e point to master 2015-01-29 20:38:36 -08:00
Guillermo Rauch
0935b81da2 Merge pull request #1963 from michael-luo/bugfix/1956
bugfix/1956 test for don't reuse same-namespace connections
2015-01-29 20:34:38 -08:00
Michael Luo
afa871bb8a bugfix/1956 test for don't reuse same-namspace connections 2015-01-24 20:19:16 -08:00
Guillermo Rauch
1b01e16a6c fix broken previous commit 2015-01-24 08:02:05 -08:00
Guillermo Rauch
bd6f638c8f package: bump to work with all objects (fixes #1955) 2015-01-24 07:06:30 -08:00
Guillermo Rauch
83b36e54ac Merge pull request #1958 from nkzawa/compress
Support compression
2015-01-23 10:04:43 -08:00
Guillermo Rauch
2f0d9d05af fix origin verification default https port [evanlucas]
for PR #1693
2015-01-22 21:41:59 +00:00
Naoyuki Kanezawa
429eb0cb7c point to the specific commit 2015-01-22 05:26:37 +09:00
Naoyuki Kanezawa
ac8e8598d7 support compression 2015-01-22 05:01:45 +09:00
23 changed files with 1288 additions and 235 deletions

25
.github/ISSUE_TEMPLATE.md vendored Normal file
View 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
View 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)

2
.gitignore vendored
View File

@@ -9,3 +9,5 @@ lib-cov
benchmarks/*.png
node_modules
coverage
.idea
dist

View File

@@ -1,4 +0,0 @@
support
test
examples
.gitignore

View File

@@ -1,16 +1,28 @@
sudo: false
before_install:
- npm install -g npm@'>=1.4.3'
language: node_js
node_js:
- "0.8"
- "0.10"
- "0.11"
- "0.12"
- "4"
- "node"
git:
depth: 1
matrix:
fast_finish: true
allow_failures:
- node_js: "0.11"
include:
- node_js: '0.10'
env: TEST_VERSION=compat
- node_js: '0.12'
env: TEST_VERSION=compat
- node_js: '4'
env: TEST_VERSION=compat
#matrix:
#fast_finish: true
#allow_failures:
#- node_js: "0.11"
notifications:
irc: "irc.freenode.org#socket.io"

View File

@@ -1,4 +1,137 @@
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
==================
* [feature] stop append /# before id when no namespace (#2508)
* [feature] Add a 'disconnecting' event to access to socket.rooms upon disconnection (#2332)
* [fix] Fix query string management (#2422)
* [fix] add quote to exec paths, prevent error when spaces in path (#2508)
* [docs] Prevent mixup for new programmers (#2599)
* [example] Fix chat display in Firefox (#2477)
* [chore] Add gulp & babel in the build process (#2471)
* [chore] Bump engine.io to 1.7.0 (#2707)
* [chore] Remove unused zuul-ngrok dependency (#2708)
* [chore] Point towards current master of socket.io-client (#2710)
* [chore] Restrict files included in npm package (#2709)
* [chore] Link build badge to master branch (#2549)
1.4.8 / 2016-06-23
==================
* package: bump `engine.io`
1.4.7 / 2016-06-23
==================
* package: bump `engine.io`
1.4.6 / 2016-05-02
==================
* package: bump engine.io
1.4.5 / 2016-01-26
==================
* fix closing the underlying `http.Server`
1.4.4 / 2016-01-10
==================
* package: bump `engine.io`
1.4.3 / 2016-01-08
==================
* bump `socket.io-client`
1.4.2 / 2016-01-07
==================
* bump `engine.io`
1.4.1 / 2016-01-07
==================
* version bump
1.4.0 / 2015-11-28
==================
* socket.io: increase large binary data test timeout
* package: bump `engine.io` for release
* trigger callback even when joining an already joined room
* package: bump parser
* namespace: clear rooms flag after a clients call (fixes #1978)
* package: bump `socket.io-parser`
* fixed tests with large data
* fixed a typo in the example code
* package: bump mocha
* package: bump `has-binary` and `zuul-ngrok`
* package: bump `engine.io` and `socket.io-client`
* README: clarified documentation of Socket.in
* README: fixed up legacy repo links
* test: better timeout for stress test
* socket: don't set request property which has a getter
* removed proxy index file
* support flags on namespace
* improve Socket#packet and Client#packet
* socket: warn node_redis-style about missing `error`
* test: added failing test
* test: increase timeout for large binary data test
* package: bump `has-binary` to work with all objects (fixes #1955)
* fix origin verification default https port [evanlucas]
* support compression [nkzawa]
* changed type of `Client#sockets`, `Namespace#sockets` and `Socket#rooms` to maps (instead of arrays)
1.3.7 / 2015-09-21
==================
* package: bump `socket.io-client` for node4 compatibility
* package: bump `engine.io` for node4 compatibility
1.3.6 / 2015-07-14
==================
* package: bump `engine.io` to fix build on windows
1.3.5 / 2015-03-03
==================
* package: bump `socket.io-parser`
1.3.4 / 2015-02-14
==================

View File

@@ -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

View File

@@ -1,15 +1,8 @@
REPORTER = dot
test:
@./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--slow 200ms \
--bail
@./node_modules/.bin/gulp test
test-cov:
@./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- \
--reporter $(REPORTER) \
test/
@./node_modules/.bin/gulp test-cov
.PHONY: test

177
Readme.md
View File

@@ -1,9 +1,12 @@
# socket.io
[![Build Status](https://secure.travis-ci.org/Automattic/socket.io.svg)](http://travis-ci.org/Automattic/socket.io)
![NPM version](https://badge.fury.io/js/socket.io.svg)
![Downloads](http://img.shields.io/npm/dm/socket.io.svg?style=flat)
[![Build Status](https://secure.travis-ci.org/socketio/socket.io.svg?branch=master)](https://travis-ci.org/socketio/socket.io)
[![Dependency Status](https://david-dm.org/socketio/socket.io.svg)](https://david-dm.org/socketio/socket.io)
[![devDependency Status](https://david-dm.org/socketio/socket.io/dev-status.svg)](https://david-dm.org/socketio/socket.io#info=devDependencies)
[![NPM version](https://badge.fury.io/js/socket.io.svg)](https://www.npmjs.com/package/socket.io)
![Downloads](https://img.shields.io/npm/dm/socket.io.svg?style=flat)
[![](http://slack.socket.io/badge.svg?)](http://slack.socket.io)
## How to use
@@ -13,9 +16,9 @@ HTTP server listening on port `3000`.
```js
var server = require('http').createServer();
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('event', function(data){});
socket.on('disconnect', function(){});
io.on('connection', function(client){
client.on('event', function(data){});
client.on('disconnect', function(){});
});
server.listen(3000);
```
@@ -24,7 +27,7 @@ server.listen(3000);
```js
var io = require('socket.io')();
io.on('connection', function(socket){});
io.on('connection', function(client){});
io.listen(3000);
```
@@ -85,7 +88,7 @@ server.listen(3000);
The same options passed to socket.io are always passed to
the `engine.io` `Server` that gets created. See engine.io
[options](https://github.com/learnboost/engine.io#methods-1)
[options](https://github.com/socketio/engine.io#methods-1)
as reference.
### Server(srv:http#Server, opts:Object)
@@ -127,7 +130,7 @@ server.listen(3000);
Sets the adapter `v`. Defaults to an instance of the `Adapter` that
ships with socket.io which is memory based. See
[socket.io-adapter](https://github.com/Automattic/socket.io-adapter).
[socket.io-adapter](https://github.com/socketio/socket.io-adapter).
If no arguments are supplied this method returns the current value.
@@ -144,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/troygoode/node-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
@@ -195,9 +198,14 @@ server.listen(3000);
For other available methods, see `Namespace` below.
### Server#close
### Server#close([fn:Function])
Closes socket 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');
@@ -240,6 +248,40 @@ server.listen(3000);
Hash of `Socket` objects that are connected to this namespace indexed
by `id`.
### Namespace#clients(fn:Function)
Gets a list of client IDs connected to this namespace (across all nodes if applicable).
An example to get all clients in a namespace:
```js
var io = require('socket.io')();
io.of('/chat').clients(function(error, clients){
if (error) throw error;
console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD]
});
```
An example to get all clients in namespace's room:
```js
var io = require('socket.io')();
io.of('/chat').in('general').clients(function(error, clients){
if (error) throw error;
console.log(clients); // => [Anw2LatarvGVVXEIAAAD]
});
```
As with broadcasting, the default is all clients from the default namespace ('/'):
```js
var io = require('socket.io')();
io.clients(function(error, clients){
if (error) throw error;
console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});
```
### Namespace#use(fn:Function):Namespace
Registers a middleware, which is a function that gets executed for
@@ -263,10 +305,33 @@ server.listen(3000);
A `Socket` is the fundamental class for interacting with browser
clients. A `Socket` belongs to a certain `Namespace` (by default `/`)
and uses an underlying `Client` to communicate.
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#rooms:Array
### Socket#use(fn:Function):Socket
A list of strings identifying the rooms this socket is in.
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
room name.
### Socket#client:Client
@@ -275,7 +340,8 @@ server.listen(3000);
### Socket#conn:Socket
A reference to the underlying `Client` transport connection (engine.io
`Socket` object).
`Socket` object). This allows access to the IO transport layer, which
still (mostly) abstracts the actual TCP/IP socket.
### Socket#request:Request
@@ -285,62 +351,100 @@ server.listen(3000);
### Socket#id:String
A unique identifier for the socket session, that comes from the
A unique identifier for the session, that comes from the
underlying `Client`.
### Socket#emit(name:String[, …]):Socket
Emits an event to the socket identified by the string `name`. Any
other parameters can be included.
Emits an event identified by the string `name` to the client.
Any other parameters can be included.
All datastructures are supported, including `Buffer`. JavaScript
functions can't be serialized/deserialized.
```js
var io = require('socket.io')();
io.on('connection', function(socket){
socket.emit('an event', { some: 'data' });
io.on('connection', function(client){
client.emit('an event', { some: 'data' });
});
```
### Socket#join(name:String[, fn:Function]):Socket
Adds the socket to the `room`, and fires optionally a callback `fn`
Adds the client to the `room`, and fires optionally a callback `fn`
with `err` signature (if any).
The socket is automatically a member of a room identified with its
The client is automatically a member of a room identified with its
session id (see `Socket#id`).
The mechanics of joining rooms are handled by the `Adapter`
that has been configured (see `Server#adapter` above), defaulting to
[socket.io-adapter](https://github.com/Automattic/socket.io-adapter).
[socket.io-adapter](https://github.com/socketio/socket.io-adapter).
### Socket#leave(name:String[, fn:Function]):Socket
Removes the socket from `room`, and fires optionally a callback `fn`
Removes the client from `room`, and fires optionally a callback `fn`
with `err` signature (if any).
**Rooms are left automatically upon disconnection**.
The mechanics of leaving rooms are handled by the `Adapter`
that has been configured (see `Server#adapter` above), defaulting to
[socket.io-adapter](https://github.com/Automattic/socket.io-adapter).
[socket.io-adapter](https://github.com/socketio/socket.io-adapter).
### Socket#to(room:String):Socket
### Socket#in(room:String):Socket
Sets a modifier for a subsequent event emission that the event will
only be _broadcasted_ to sockets that have joined the given `room`.
only be _broadcasted_ to clients that have joined the given `room`.
To emit to multiple rooms, you can call `to` several times.
```js
var io = require('socket.io')();
io.on('connection', function(socket){
socket.to('others').emit('an event', { some: 'data' });
io.on('connection', function(client){
client.to('others').emit('an event', { some: 'data' });
});
```
### Socket#in(room:String):Socket
Same as `Socket#to`
### Socket#compress(v:Boolean):Socket
Sets a modifier for a subsequent event emission that the event data will
only be _compressed_ if the value is `true`. Defaults to `true` when you don't call the method.
```js
var io = require('socket.io')();
io.on('connection', function(client){
client.compress(false).emit('an event', { some: 'data' });
});
```
### Socket#disconnect(close:Boolean):Socket
Disconnects this client. If value of close is `true`, closes the underlying connection.
Otherwise, it just disconnects the namespace.
#### Events
- `disconnect`
- Fired upon disconnection.
- **Arguments**
- `String`: the reason of the disconnection (either client or server-side)
- `error`
- Fired when an error occurs.
- **Arguments**
- `Object`: error data
- `disconnecting`
- Fired when the client is going to be disconnected (but hasn't left its `rooms` yet).
- **Arguments**
- `String`: the reason of the disconnection (either client or server-side)
These are reserved events (along with `connect`, `newListener` and `removeListener`) which cannot be used as event names.
### Client
The `Client` class represents an incoming transport (engine.io)
@@ -359,7 +463,7 @@ server.listen(3000);
## Debug / logging
Socket.IO is powered by [debug](http://github.com/visionmedia/debug).
Socket.IO is powered by [debug](https://github.com/visionmedia/debug).
In order to see all the debug output, run your app with the environment variable
`DEBUG` including the desired scope.
@@ -369,6 +473,17 @@ To see the output from all of Socket.IO's debugging scopes you can use:
DEBUG=socket.io* node myapp
```
## Testing
```
npm test
```
This runs the `gulp` task `test`. By default the test will be run with the source code in `lib` directory.
Set the environmental variable `TEST_VERSION` to `compat` to test the transpiled es5-compat version of the code.
The `gulp` task `test` will always transpile the source code into es5 and export to `dist` first before running the test.
## License
MIT
[MIT](LICENSE)

View File

@@ -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

View File

@@ -14,8 +14,6 @@ app.use(express.static(__dirname + '/public'));
// Chatroom
// usernames which are currently connected to the chat
var usernames = {};
var numUsers = 0;
io.on('connection', function (socket) {
@@ -32,10 +30,10 @@ io.on('connection', function (socket) {
// when the client emits 'add user', this listens and executes
socket.on('add user', function (username) {
if (addedUser) return;
// we store the username in the socket session for this client
socket.username = username;
// add the client's username to the global list
usernames[username] = username;
++numUsers;
addedUser = true;
socket.emit('login', {
@@ -64,9 +62,7 @@ io.on('connection', function (socket) {
// when the user disconnects.. perform this
socket.on('disconnect', function () {
// remove the username from global usernames list
if (addedUser) {
delete usernames[socket.username];
--numUsers;
// echo globally that this client has left

View File

@@ -7,6 +7,9 @@
"private": true,
"license": "BSD",
"dependencies": {
"express": "3.4.8"
"express": "4.13.4"
},
"scripts": {
"start": "node index.js"
}
}
}

View File

@@ -7,7 +7,7 @@ $(function() {
'#3b88eb', '#3824aa', '#a700ff', '#d300e7'
];
// Initialize varibles
// Initialize variables
var $window = $(window);
var $usernameInput = $('.usernameInput'); // Input for username
var $messages = $('.messages'); // Messages area
@@ -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');
});
});

View File

@@ -128,7 +128,6 @@ ul {
}
.username {
float: left;
font-weight: 700;
overflow: hidden;
padding-right: 15px;

69
gulpfile.js Normal file
View File

@@ -0,0 +1,69 @@
const gulp = require('gulp');
const mocha = require('gulp-mocha');
const babel = require("gulp-babel");
const istanbul = require('gulp-istanbul');
const help = require('gulp-task-listing');
const del = require('del');
gulp.task('help', help);
gulp.task('default', ['transpile']);
const TRANSPILE_DEST_DIR = './dist';
// By default, individual js files are transformed by babel and exported to /dist
gulp.task('transpile', function () {
return gulp.src("lib/*.js")
.pipe(babel({ "presets": ["es2015"] }))
.pipe(gulp.dest(TRANSPILE_DEST_DIR));
});
gulp.task('clean', function () {
return del([TRANSPILE_DEST_DIR]);
})
gulp.task('test', ['transpile'], function(){
return gulp.src('test/socket.io.js', {read: false})
.pipe(mocha({
slow: 200,
reporter: 'spec',
bail: true,
timeout: 10000
}))
.once('error', function (err) {
console.error(err.stack);
process.exit(1);
})
.once('end', function () {
process.exit();
});
});
gulp.task('set-compat-node-env', function() {
process.env.TEST_VERSION = 'compat';
});
gulp.task('test-compat', ['set-compat-node-env', 'test']);
gulp.task('istanbul-pre-test', function () {
return gulp.src(['lib/**/*.js'])
// Covering files
.pipe(istanbul())
// Force `require` to return covered files
.pipe(istanbul.hookRequire());
});
gulp.task('test-cov', ['istanbul-pre-test'], function(){
return gulp.src('test/socket.io.js', {read: false})
.pipe(mocha({
reporter: 'dot'
}))
.pipe(istanbul.writeReports())
.once('error', function (err){
console.error(err.stack);
process.exit(1);
})
.once('end', function (){
process.exit();
});
});

View File

@@ -1,2 +0,0 @@
module.exports = require('./lib');

View File

@@ -5,6 +5,7 @@
var parser = require('socket.io-parser');
var debug = require('debug')('socket.io:client');
var url = require('url');
/**
* Module exports.
@@ -16,7 +17,7 @@ module.exports = Client;
* Client constructor.
*
* @param {Server} server instance
* @param {Socket} connection
* @param {Socket} conn
* @api private
*/
@@ -28,7 +29,7 @@ function Client(server, conn){
this.id = conn.id;
this.request = conn.request;
this.setup();
this.sockets = [];
this.sockets = {};
this.nsps = {};
this.connectBuffer = [];
}
@@ -54,25 +55,26 @@ Client.prototype.setup = function(){
/**
* Connects a client to a namespace.
*
* @param {String} namespace name
* @param {String} name namespace
* @api private
*/
Client.prototype.connect = function(name){
Client.prototype.connect = function(name, query){
debug('connecting to namespace %s', name);
if (!this.server.nsps[name]) {
var nsp = this.server.nsps[name];
if (!nsp) {
this.packet({ type: parser.ERROR, nsp: name, data : 'Invalid namespace'});
return;
}
var nsp = this.server.of(name);
if ('/' != name && !this.nsps['/']) {
this.connectBuffer.push(name);
return;
}
var self = this;
var socket = nsp.add(this, function(){
self.sockets.push(socket);
var socket = nsp.add(this, query, function(){
self.sockets[socket.id] = socket;
self.nsps[nsp.name] = socket;
if ('/' == nsp.name && self.connectBuffer.length > 0) {
@@ -89,12 +91,12 @@ Client.prototype.connect = function(name){
*/
Client.prototype.disconnect = function(){
var socket;
// we don't use a for loop because the length of
// `sockets` changes upon each iteration
while (socket = this.sockets.shift()) {
socket.disconnect();
for (var id in this.sockets) {
if (this.sockets.hasOwnProperty(id)) {
this.sockets[id].disconnect();
}
}
this.sockets = {};
this.close();
};
@@ -105,10 +107,9 @@ Client.prototype.disconnect = function(){
*/
Client.prototype.remove = function(socket){
var i = this.sockets.indexOf(socket);
if (~i) {
var nsp = this.sockets[i].nsp.name;
this.sockets.splice(i, 1);
if (this.sockets.hasOwnProperty(socket.id)) {
var nsp = this.sockets[socket.id].nsp.name;
delete this.sockets[socket.id];
delete this.nsps[nsp];
} else {
debug('ignoring remove for %s', socket.id);
@@ -133,25 +134,25 @@ Client.prototype.close = function(){
* Writes a packet to the transport.
*
* @param {Object} packet object
* @param {Boolean} whether packet is already encoded
* @param {Boolean} whether packet is volatile
* @param {Object} opts
* @api private
*/
Client.prototype.packet = function(packet, preEncoded, volatile){
Client.prototype.packet = function(packet, opts){
opts = opts || {};
var self = this;
// this writes to the actual connection
function writeToEngine(encodedPackets) {
if (volatile && !self.conn.transport.writable) return;
if (opts.volatile && !self.conn.transport.writable) return;
for (var i = 0; i < encodedPackets.length; i++) {
self.conn.write(encodedPackets[i]);
self.conn.write(encodedPackets[i], { compress: opts.compress });
}
}
if ('open' == this.conn.readyState) {
debug('writing packet %j', packet);
if(!preEncoded) { // not broadcasting, need to encode
if (!opts.preEncoded) { // not broadcasting, need to encode
this.encoder.encode(packet, function (encodedPackets) { // encode, then write results to engine
writeToEngine(encodedPackets);
});
@@ -186,11 +187,13 @@ Client.prototype.ondata = function(data){
Client.prototype.ondecoded = function(packet) {
if (parser.CONNECT == packet.type) {
this.connect(packet.nsp);
this.connect(url.parse(packet.nsp).pathname, url.parse(packet.nsp, true).query);
} 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);
}
@@ -200,14 +203,16 @@ Client.prototype.ondecoded = function(packet) {
/**
* Handles an error.
*
* @param {Objcet} error object
* @param {Object} err object
* @api private
*/
Client.prototype.onerror = function(err){
this.sockets.forEach(function(socket){
socket.onerror(err);
});
for (var id in this.sockets) {
if (this.sockets.hasOwnProperty(id)) {
this.sockets[id].onerror(err);
}
}
this.onclose('client error');
};
@@ -225,10 +230,12 @@ Client.prototype.onclose = function(reason){
this.destroy();
// `nsps` and `sockets` are cleaned up seamlessly
var socket;
while (socket = this.sockets.shift()) {
socket.onclose(reason);
for (var id in this.sockets) {
if (this.sockets.hasOwnProperty(id)) {
this.sockets[id].onclose(reason);
}
}
this.sockets = {};
this.decoder.destroy(); // clean up decoder
};

View File

@@ -5,11 +5,11 @@
var http = require('http');
var read = require('fs').readFileSync;
var parse = require('url').parse;
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');
@@ -25,13 +25,13 @@ module.exports = Server;
* Socket.IO client source.
*/
var clientSource = read(require.resolve('socket.io-client/socket.io.js'), 'utf-8');
var clientSource = undefined;
/**
* Server constructor.
*
* @param {http.Server|Number|Object} http server, port or options
* @param {Object} options
* @param {http.Server|Number|Object} srv http server, port or options
* @param {Object} [opts]
* @api public
*/
@@ -54,8 +54,8 @@ function Server(srv, opts){
/**
* Server request verification function, that checks for allowed origins
*
* @param {http.IncomingMessage} request
* @param {Function} callback to be called with the result: `fn(err, success)`
* @param {http.IncomingMessage} req request
* @param {Function} fn callback to be called with the result: `fn(err, success)`
*/
Server.prototype.checkRequest = function(req, fn) {
@@ -69,7 +69,10 @@ Server.prototype.checkRequest = function(req, fn) {
if (origin) {
try {
var parts = url.parse(origin);
parts.port = parts.port || 80;
var defaultPort = 'https:' == parts.protocol ? 443 : 80;
parts.port = parts.port != null
? parts.port
: defaultPort;
var ok =
~this._origins.indexOf(parts.hostname + ':' + parts.port) ||
~this._origins.indexOf(parts.hostname + ':*') ||
@@ -84,7 +87,7 @@ Server.prototype.checkRequest = function(req, fn) {
/**
* Sets/gets whether client code is being served.
*
* @param {Boolean} whether to serve client code
* @param {Boolean} v whether to serve client code
* @return {Server|Boolean} self when setting or value when getting
* @api public
*/
@@ -92,6 +95,11 @@ 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/socket.io.js'), 'utf-8');
}
return this;
};
@@ -107,7 +115,7 @@ var oldSettings = {
};
/**
* Backwards compatiblity.
* Backwards compatibility.
*
* @api public
*/
@@ -137,7 +145,7 @@ Server.prototype.set = function(key, val){
/**
* Sets the client serving path.
*
* @param {String} pathname
* @param {String} v pathname
* @return {Server|String} self when setting or value when getting
* @api public
*/
@@ -151,7 +159,7 @@ Server.prototype.path = function(v){
/**
* Sets the adapter for rooms.
*
* @param {Adapter} pathname
* @param {Adapter} v pathname
* @return {Server|Adapter} self when setting or value when getting
* @api public
*/
@@ -170,7 +178,7 @@ Server.prototype.adapter = function(v){
/**
* Sets the allowed origins for requests.
*
* @param {String} origins
* @param {String} v origins
* @return {Server|Adapter} self when setting or value when getting
* @api public
*/
@@ -219,7 +227,7 @@ Server.prototype.attach = function(srv, opts){
opts = opts || {};
opts.path = opts.path || this.path();
// set origins verification
opts.allowRequest = this.checkRequest.bind(this);
opts.allowRequest = opts.allowRequest || this.checkRequest.bind(this);
// initialize engine
debug('creating engine.io instance with opts %j', opts);
@@ -240,7 +248,7 @@ Server.prototype.attach = function(srv, opts){
/**
* Attaches the static file serving.
*
* @param {Function|http.Server} http server
* @param {Function|http.Server} srv http server
* @api private
*/
@@ -251,7 +259,7 @@ Server.prototype.attachServe = function(srv){
var self = this;
srv.removeAllListeners('request');
srv.on('request', function(req, res) {
if (0 == req.url.indexOf(url)) {
if (0 === req.url.indexOf(url)) {
self.serve(req, res);
} else {
for (var i = 0; i < evs.length; i++) {
@@ -270,9 +278,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();
@@ -282,7 +294,7 @@ 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.writeHead(200);
res.end(clientSource);
};
@@ -290,7 +302,7 @@ Server.prototype.serve = function(req, res){
/**
* Binds socket.io to an engine.io instance.
*
* @param {engine.Server} engine.io (or compatible) server
* @param {engine.Server} engine engine.io (or compatible) server
* @return {Server} self
* @api public
*/
@@ -304,7 +316,7 @@ Server.prototype.bind = function(engine){
/**
* Called with each incoming transport connection.
*
* @param {engine.Socket} socket
* @param {engine.Socket} conn
* @return {Server} self
* @api public
*/
@@ -319,38 +331,44 @@ Server.prototype.onconnection = function(conn){
/**
* Looks up a namespace.
*
* @param {String} nsp name
* @param {Function} optional, nsp `connection` ev handler
* @param {String} name nsp name
* @param {Function} [fn] optional, nsp `connection` ev handler
* @api public
*/
Server.prototype.of = function(name, fn){
if (String(name)[0] !== '/') name = '/' + name;
if (!this.nsps[name]) {
var nsp = this.nsps[name];
if (!nsp) {
debug('initializing namespace %s', name);
var nsp = new Namespace(this, name);
nsp = new Namespace(this, name);
this.nsps[name] = nsp;
}
if (fn) this.nsps[name].on('connect', fn);
return this.nsps[name];
if (fn) nsp.on('connect', fn);
return nsp;
};
/**
* Closes server connection
*
* @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed
* @api public
*/
Server.prototype.close = function(){
this.nsps['/'].sockets.forEach(function(socket){
socket.onclose();
});
Server.prototype.close = function(fn){
for (var id in this.nsps['/'].sockets) {
if (this.nsps['/'].sockets.hasOwnProperty(id)) {
this.nsps['/'].sockets[id].onclose();
}
}
this.engine.close();
if(this.httpServer){
this.httpServer.close();
if (this.httpServer) {
this.httpServer.close(fn);
} else {
fn && fn();
}
};
@@ -358,17 +376,23 @@ Server.prototype.close = function(){
* Expose main namespace (/).
*/
['on', 'to', 'in', 'use', 'emit', 'send', 'write'].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(name){
this.flags.push(name);
return this;
Object.defineProperty(Server.prototype, flag, {
get: function() {
this.sockets.flags = this.sockets.flags || {};
this.sockets.flags[flag] = true;
return this;
}
});
});

View File

@@ -7,7 +7,7 @@ var Socket = require('./socket');
var Emitter = require('events').EventEmitter;
var parser = require('socket.io-parser');
var debug = require('debug')('socket.io:namespace');
var hasBin = require('has-binary-data');
var hasBin = require('has-binary');
/**
* Module exports.
@@ -29,7 +29,10 @@ exports.events = [
* Flags.
*/
exports.flags = ['json'];
exports.flags = [
'json',
'volatile'
];
/**
* `EventEmitter#emit` reference.
@@ -48,11 +51,10 @@ var emit = Emitter.prototype.emit;
function Namespace(server, name){
this.name = name;
this.server = server;
this.sockets = [];
this.sockets = {};
this.connected = {};
this.fns = [];
this.ids = 0;
this.acks = {};
this.initAdapter();
}
@@ -67,10 +69,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;
}
});
});
@@ -102,7 +106,7 @@ Namespace.prototype.use = function(fn){
* Executes the middleware for an incoming client.
*
* @param {Socket} socket that will get added
* @param {Function} last fn call in the middleware
* @param {Function} fn last fn call in the middleware
* @api private
*/
@@ -135,7 +139,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;
@@ -148,9 +152,9 @@ Namespace.prototype['in'] = function(name){
* @api private
*/
Namespace.prototype.add = function(client, fn){
Namespace.prototype.add = function(client, query, fn){
debug('adding socket to nsp %s', this.name);
var socket = new Socket(this, client);
var socket = new Socket(this, client, query);
var self = this;
this.run(socket, function(err){
process.nextTick(function(){
@@ -158,7 +162,7 @@ Namespace.prototype.add = function(client, fn){
if (err) return socket.error(err.data || err.message);
// track socket
self.sockets.push(socket);
self.sockets[socket.id] = socket;
// it's paramount that the internal `onconnect` logic
// fires before user-set events to prevent state order
@@ -185,9 +189,8 @@ Namespace.prototype.add = function(client, fn){
*/
Namespace.prototype.remove = function(socket){
var i = this.sockets.indexOf(socket);
if (~i) {
this.sockets.splice(i, 1);
if (this.sockets.hasOwnProperty(socket.id)) {
delete this.sockets[socket.id];
} else {
debug('ignoring remove for %s', socket.id);
}
@@ -240,3 +243,32 @@ Namespace.prototype.write = function(){
this.emit.apply(this, args);
return this;
};
/**
* Gets a list of clients.
*
* @return {Namespace} self
* @api public
*/
Namespace.prototype.clients = function(fn){
this.adapter.clients(this.rooms, fn);
// delete rooms flag for scenario:
// .in('room').clients() (GH-1978)
delete this.rooms;
return this;
};
/**
* Sets the compress flag.
*
* @param {Boolean} compress if `true`, compresses the sending data
* @return {Socket} self
* @api public
*/
Namespace.prototype.compress = function(compress){
this.flags = this.flags || {};
this.flags.compress = compress;
return this;
};

View File

@@ -7,7 +7,8 @@ var Emitter = require('events').EventEmitter;
var parser = require('socket.io-parser');
var url = require('url');
var debug = require('debug')('socket.io:socket');
var hasBin = require('has-binary-data');
var hasBin = require('has-binary');
var assign = require('object-assign');
/**
* Module exports.
@@ -25,6 +26,7 @@ exports.events = [
'error',
'connect',
'disconnect',
'disconnecting',
'newListener',
'removeListener'
];
@@ -55,19 +57,19 @@ var emit = Emitter.prototype.emit;
* @api public
*/
function Socket(nsp, client){
function Socket(nsp, client, query){
this.nsp = nsp;
this.server = nsp.server;
this.adapter = this.nsp.adapter;
this.id = client.id;
this.request = client.request;
this.id = nsp.name !== '/' ? nsp.name + '#' + client.id : client.id;
this.client = client;
this.conn = client.conn;
this.rooms = [];
this.rooms = {};
this.acks = {};
this.connected = true;
this.disconnected = false;
this.handshake = this.buildHandshake();
this.handshake = this.buildHandshake(query);
this.fns = [];
}
/**
@@ -81,21 +83,25 @@ 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;
}
});
});
/**
* `request` engine.io shorcut.
* `request` engine.io shortcut.
*
* @api public
*/
Socket.prototype.__defineGetter__('request', function(){
return this.conn.request;
Object.defineProperty(Socket.prototype, 'request', {
get: function() {
return this.conn.request;
}
});
/**
@@ -104,7 +110,13 @@ Socket.prototype.__defineGetter__('request', function(){
* @api private
*/
Socket.prototype.buildHandshake = function(){
Socket.prototype.buildHandshake = function(query){
var self = this;
function buildQuery(){
var requestQuery = url.parse(self.request.url, true).query;
//if socket-specific query exist, replace query strings in requestQuery
return assign({}, query, requestQuery);
}
return {
headers: this.request.headers,
time: (new Date) + '',
@@ -113,7 +125,7 @@ Socket.prototype.buildHandshake = function(){
secure: !!this.request.connection.encrypted,
issued: +(new Date),
url: this.request.url,
query: url.parse(this.request.url, true).query || {}
query: buildQuery()
};
};
@@ -132,10 +144,11 @@ Socket.prototype.emit = function(ev){
var packet = {};
packet.type = hasBin(args) ? parser.BINARY_EVENT : parser.EVENT;
packet.data = args;
var flags = this.flags || {};
// access last argument to see if it's an ACK callback
if ('function' == typeof args[args.length - 1]) {
if (this._rooms || (this.flags && this.flags.broadcast)) {
if (this._rooms || flags.broadcast) {
throw new Error('Callbacks are not supported when broadcasting');
}
@@ -144,15 +157,18 @@ Socket.prototype.emit = function(ev){
packet.id = this.nsp.ids++;
}
if (this._rooms || (this.flags && this.flags.broadcast)) {
if (this._rooms || flags.broadcast) {
this.adapter.broadcast(packet, {
except: [this.id],
rooms: this._rooms,
flags: this.flags
flags: flags
});
} else {
// dispatch packet
this.packet(packet);
this.packet(packet, {
volatile: flags.volatile,
compress: flags.compress
});
}
// reset flags
@@ -196,20 +212,22 @@ Socket.prototype.write = function(){
* Writes a packet.
*
* @param {Object} packet object
* @param {Object} opts options
* @api private
*/
Socket.prototype.packet = function(packet, preEncoded){
Socket.prototype.packet = function(packet, opts){
packet.nsp = this.nsp.name;
var volatile = this.flags && this.flags.volatile;
this.client.packet(packet, preEncoded, volatile);
opts = opts || {};
opts.compress = false !== opts.compress;
this.client.packet(packet, opts);
};
/**
* Joins a room.
*
* @param {String} room
* @param {Function} optional, callback
* @param {Function} fn optional, callback
* @return {Socket} self
* @api private
*/
@@ -217,11 +235,14 @@ Socket.prototype.packet = function(packet, preEncoded){
Socket.prototype.join = function(room, fn){
debug('joining room %s', room);
var self = this;
if (~this.rooms.indexOf(room)) return this;
if (this.rooms.hasOwnProperty(room)) {
fn && fn(null);
return this;
}
this.adapter.add(this.id, room, function(err){
if (err) return fn && fn(err);
debug('joined room %s', room);
self.rooms.push(room);
self.rooms[room] = room;
fn && fn(null);
});
return this;
@@ -231,7 +252,7 @@ Socket.prototype.join = function(room, fn){
* Leaves a room.
*
* @param {String} room
* @param {Function} optional, callback
* @param {Function} fn optional, callback
* @return {Socket} self
* @api private
*/
@@ -242,10 +263,7 @@ Socket.prototype.leave = function(room, fn){
this.adapter.del(this.id, room, function(err){
if (err) return fn && fn(err);
debug('left room %s', room);
var idx = self.rooms.indexOf(room);
if (idx >= 0) {
self.rooms.splice(idx, 1);
}
delete self.rooms[room];
fn && fn(null);
});
return this;
@@ -259,11 +277,11 @@ Socket.prototype.leave = function(room, fn){
Socket.prototype.leaveAll = function(){
this.adapter.delAll(this.id);
this.rooms = [];
this.rooms = {};
};
/**
* Called by `Namespace` upon succesful
* Called by `Namespace` upon successful
* middleware execution (ie: authorization).
*
* @api private
@@ -271,9 +289,9 @@ Socket.prototype.leaveAll = function(){
Socket.prototype.onconnect = function(){
debug('socket connected - writing packet');
this.nsp.connected[this.id] = this;
this.join(this.id);
this.packet({ type: parser.CONNECT });
this.nsp.connected[this.id] = this;
};
/**
@@ -327,13 +345,13 @@ Socket.prototype.onevent = function(packet){
args.push(this.ack(packet.id));
}
emit.apply(this, args);
this.dispatch(args);
};
/**
* Produces an ack callback to emit with an event.
*
* @param {Number} packet id
* @param {Number} id packet id
* @api private
*/
@@ -352,6 +370,8 @@ Socket.prototype.ack = function(id){
type: type,
data: args
});
sent = true;
};
};
@@ -402,13 +422,14 @@ Socket.prototype.onerror = function(err){
* Called upon closing. Called by `Client`.
*
* @param {String} reason
* @param {Error} optional error object
* @throw {Error} optional error object
* @api private
*/
Socket.prototype.onclose = function(reason){
if (!this.connected) return this;
debug('closing socket - reason %s', reason);
this.emit('disconnecting', reason);
this.leaveAll();
this.nsp.remove(this);
this.client.remove(this);
@@ -421,7 +442,7 @@ Socket.prototype.onclose = function(reason){
/**
* Produces an `error` packet.
*
* @param {Object} error object
* @param {Object} err error object
* @api private
*/
@@ -432,7 +453,7 @@ Socket.prototype.error = function(err){
/**
* Disconnects this client.
*
* @param {Boolean} if `true`, closes the underlying connection
* @param {Boolean} close if `true`, closes the underlying connection
* @return {Socket} self
* @api public
*/
@@ -447,3 +468,77 @@ Socket.prototype.disconnect = function(close){
}
return this;
};
/**
* Sets the compress flag.
*
* @param {Boolean} compress if `true`, compresses the sending data
* @return {Socket} self
* @api public
*/
Socket.prototype.compress = function(compress){
this.flags = this.flags || {};
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.emit('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);
};

View File

@@ -1,6 +1,6 @@
{
"name": "socket.io",
"version": "1.3.4",
"version": "1.6.0",
"description": "node.js realtime framework server",
"keywords": [
"realtime",
@@ -11,27 +11,40 @@
"socket",
"io"
],
"main": "./lib/index",
"files": [
"lib/"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/Automattic/socket.io"
"url": "git://github.com/socketio/socket.io"
},
"scripts": {
"test": "mocha --reporter dot --slow 200ms --bail"
"test": "gulp test"
},
"dependencies": {
"engine.io": "1.5.1",
"socket.io-parser": "2.2.3",
"socket.io-client": "1.3.4",
"socket.io-adapter": "0.3.1",
"has-binary-data": "0.1.3",
"debug": "2.1.0"
"debug": "2.3.3",
"engine.io": "1.8.0",
"has-binary": "0.1.7",
"object-assign": "4.1.0",
"socket.io-adapter": "0.5.0",
"socket.io-client": "1.6.0",
"socket.io-parser": "2.3.1"
},
"devDependencies": {
"mocha": "1.16.2",
"babel-preset-es2015": "6.3.13",
"del": "2.2.0",
"expect.js": "0.3.1",
"supertest": "0.8.2",
"superagent": "0.17.0",
"istanbul": "0.2.3"
"gulp": "3.9.0",
"gulp-babel": "6.1.1",
"gulp-istanbul": "0.10.3",
"gulp-mocha": "2.2.0",
"gulp-task-listing": "1.0.1",
"istanbul": "0.4.1",
"mocha": "2.3.4",
"superagent": "1.6.1",
"supertest": "1.1.0"
},
"contributors": [
{

11
test/fixtures/server-close.js vendored Normal file
View File

@@ -0,0 +1,11 @@
var server = require('http').createServer();
var ioc = require('socket.io-client');
var io = require('../..')(server);
var srv = server.listen(function() {
var socket = ioc('ws://localhost:' + server.address().port);
socket.on('connect', function() {
io.close();
socket.close();
});
});

View File

@@ -1,8 +1,15 @@
var testVersion = process.env.TEST_VERSION;
var http = require('http').Server;
var io = require('..');
var io;
if (testVersion === 'compat') {
console.log('testing compat version');
io = require('../dist');
} else {
io = require('../lib');
}
var fs = require('fs');
var join = require('path').join;
var exec = require('child_process').exec;
var ioc = require('socket.io-client');
var request = require('supertest');
var expect = require('expect.js');
@@ -160,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();
@@ -172,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);
@@ -317,6 +324,43 @@ describe('socket.io', function(){
done();
});
});
it('should default to port 443 when protocol is https', function(done) {
var sockets = io({ origins: 'https://foo.example:443' }).listen('54036');
request.get('http://localhost:54036/socket.io/default/')
.set('origin', 'https://foo.example')
.query({ transport: 'polling' })
.end(function (err, res) {
expect(res.status).to.be(200);
done();
});
});
it('should allow request if custom function in opts.allowRequest returns true', function(done){
var sockets = io(http().listen(54022), { allowRequest: function (req, callback) {
return callback(null, true);
}, origins: 'http://foo.example:*' });
request.get('http://localhost:54022/socket.io/default/')
.query({ transport: 'polling' })
.end(function (err, res) {
expect(res.status).to.be(200);
done();
});
});
it('should disallow request if custom function in opts.allowRequest returns false', function(done){
var sockets = io(http().listen(54023), { allowRequest: function (req, callback) {
return callback(null, false);
} });
request.get('http://localhost:54023/socket.io/default/')
.set('origin', 'http://foo.example')
.query({ transport: 'polling' })
.end(function (err, res) {
expect(res.status).to.be(400);
done();
});
});
});
describe('close', function(){
@@ -331,12 +375,12 @@ describe('socket.io', function(){
var clientSocket = client(srv, { reconnection: false });
clientSocket.on('disconnect', function init() {
expect(sio.nsps['/'].sockets.length).to.equal(0);
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(0);
server.listen(PORT);
});
clientSocket.on('connect', function init() {
expect(sio.nsps['/'].sockets.length).to.equal(1);
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(1);
sio.close();
});
@@ -355,15 +399,15 @@ 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(sio.nsps['/'].sockets.length).to.equal(0);
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(0);
server.listen(PORT);
});
clientSocket.on('connect', function init() {
expect(sio.nsps['/'].sockets.length).to.equal(1);
expect(Object.keys(sio.nsps['/'].sockets).length).to.equal(1);
sio.close();
});
@@ -375,12 +419,31 @@ describe('socket.io', function(){
});
});
describe('graceful close', function(){
function fixture(filename) {
return '"' + process.execPath + '" "' +
join(__dirname, 'fixtures', filename) + '"';
}
it('should stop socket and timers', function(done){
exec(fixture('server-close.js'), done);
});
});
});
describe('namespaces', function(){
var Socket = require('../lib/socket');
var Namespace = require('../lib/namespace');
var Socket;
if (testVersion === 'compat') {
Socket = require('../dist/socket');
} else {
Socket = require('../lib/socket');
}
var Namespace;
if (testVersion === 'compat') {
Namespace = require('../dist/namespace');
} else {
Namespace = require('../lib/namespace');
}
it('should be accessible through .sockets', function(){
var sio = io();
expect(sio.sockets).to.be.a(Namespace);
@@ -394,6 +457,12 @@ describe('socket.io', function(){
expect(sio.emit).to.be.a('function');
expect(sio.send).to.be.a('function');
expect(sio.write).to.be.a('function');
expect(sio.clients).to.be.a('function');
expect(sio.compress).to.be.a('function');
expect(sio.json).to.be(sio);
expect(sio.volatile).to.be(sio);
expect(sio.sockets.flags).to.eql({ json: true, volatile: true });
delete sio.sockets.flags;
});
it('should automatically connect', function(done){
@@ -575,6 +644,31 @@ describe('socket.io', function(){
});
});
it('should fire a `disconnecting` event just before leaving all rooms', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv);
sio.on('connection', function(s){
s.join('a', function(){
s.disconnect();
});
var total = 2;
s.on('disconnecting', function(reason){
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
total--;
});
s.on('disconnect', function(reason){
expect(Object.keys(s.rooms)).to.eql([]);
--total || done();
});
});
});
});
it('should return error connecting to non-existent namespace', function(done){
var srv = http();
var sio = io(srv);
@@ -586,6 +680,220 @@ describe('socket.io', function(){
});
});
});
it('should not reuse same-namespace connections', function(done){
var srv = http();
var sio = io(srv);
var connections = 0;
srv.listen(function() {
var clientSocket1 = client(srv);
var clientSocket2 = client(srv);
sio.on('connection', function() {
connections++;
if (connections === 2) {
done();
}
});
});
});
it('should find all clients in a namespace', function(done){
var srv = http();
var sio = io(srv);
var chatSids = [];
var otherSid = null;
srv.listen(function(){
var c1 = client(srv, '/chat');
var c2 = client(srv, '/chat', {forceNew: true});
var c3 = client(srv, '/other', {forceNew: true});
var total = 3;
sio.of('/chat').on('connection', function(socket){
chatSids.push(socket.id);
--total || getClients();
});
sio.of('/other').on('connection', function(socket){
otherSid = socket.id;
--total || getClients();
});
});
function getClients() {
sio.of('/chat').clients(function(error, sids) {
expect(error).to.not.be.ok();
expect(sids).to.contain(chatSids[0]);
expect(sids).to.contain(chatSids[1]);
expect(sids).to.not.contain(otherSid);
done();
});
}
});
it('should find all clients in a namespace room', function(done){
var srv = http();
var sio = io(srv);
var chatFooSid = null;
var chatBarSid = null;
var otherSid = null;
srv.listen(function(){
var c1 = client(srv, '/chat');
var c2 = client(srv, '/chat', {forceNew: true});
var c3 = client(srv, '/other', {forceNew: true});
var chatIndex = 0;
var total = 3;
sio.of('/chat').on('connection', function(socket){
if (chatIndex++) {
socket.join('foo', function() {
chatFooSid = socket.id;
--total || getClients();
});
} else {
socket.join('bar', function() {
chatBarSid = socket.id;
--total || getClients();
});
}
});
sio.of('/other').on('connection', function(socket){
socket.join('foo', function() {
otherSid = socket.id;
--total || getClients();
});
});
});
function getClients() {
sio.of('/chat').in('foo').clients(function(error, sids) {
expect(error).to.not.be.ok();
expect(sids).to.contain(chatFooSid);
expect(sids).to.not.contain(chatBarSid);
expect(sids).to.not.contain(otherSid);
done();
});
}
});
it('should find all clients across namespace rooms', function(done){
var srv = http();
var sio = io(srv);
var chatFooSid = null;
var chatBarSid = null;
var otherSid = null;
srv.listen(function(){
var c1 = client(srv, '/chat');
var c2 = client(srv, '/chat', {forceNew: true});
var c3 = client(srv, '/other', {forceNew: true});
var chatIndex = 0;
var total = 3;
sio.of('/chat').on('connection', function(socket){
if (chatIndex++) {
socket.join('foo', function() {
chatFooSid = socket.id;
--total || getClients();
});
} else {
socket.join('bar', function() {
chatBarSid = socket.id;
--total || getClients();
});
}
});
sio.of('/other').on('connection', function(socket){
socket.join('foo', function() {
otherSid = socket.id;
--total || getClients();
});
});
});
function getClients() {
sio.of('/chat').clients(function(error, sids) {
expect(error).to.not.be.ok();
expect(sids).to.contain(chatFooSid);
expect(sids).to.contain(chatBarSid);
expect(sids).to.not.contain(otherSid);
done();
});
}
});
it('should not emit volatile event after regular event', function(done) {
var srv = http();
var sio = io(srv);
var counter = 0;
srv.listen(function(){
sio.of('/chat').on('connection', function(s){
// Wait to make sure there are no packets being sent for opening the connection
setTimeout(function() {
sio.of('/chat').emit('ev', 'data');
sio.of('/chat').volatile.emit('ev', 'data');
}, 50);
});
var socket = client(srv, '/chat');
socket.on('ev', function() {
counter++;
});
});
setTimeout(function() {
expect(counter).to.be(1);
done();
}, 500);
});
it('should emit volatile event', function(done) {
var srv = http();
var sio = io(srv);
var counter = 0;
srv.listen(function(){
sio.of('/chat').on('connection', function(s){
// Wait to make sure there are no packets being sent for opening the connection
setTimeout(function() {
sio.of('/chat').volatile.emit('ev', 'data');
}, 100);
});
var socket = client(srv, '/chat');
socket.on('ev', function() {
counter++;
});
});
setTimeout(function() {
expect(counter).to.be(1);
done();
}, 500);
});
it('should enable compression by default', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv, '/chat');
sio.of('/chat').on('connection', function(s){
s.conn.once('packetCreate', function(packet) {
expect(packet.options.compress).to.be(true);
done();
});
sio.of('/chat').emit('woot', 'hi');
});
});
});
it('should disable compression', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv, '/chat');
sio.of('/chat').on('connection', function(s){
s.conn.once('packetCreate', function(packet) {
expect(packet.options.compress).to.be(false);
done();
});
sio.of('/chat').compress(false).emit('woot', 'hi');
});
});
});
});
describe('socket', function(){
@@ -871,7 +1179,7 @@ describe('socket.io', function(){
// Wait to make sure there are no packets being sent for opening the connection
setTimeout(function() {
s.volatile.emit('ev', 'data');
}, 20);
}, 100);
});
var socket = client(srv, { transports: ['polling'] });
@@ -883,7 +1191,7 @@ describe('socket.io', function(){
setTimeout(function() {
expect(counter).to.be(1);
done();
}, 200);
}, 500);
});
it('should emit volatile event (ws)', function(done) {
@@ -922,7 +1230,7 @@ describe('socket.io', function(){
setTimeout(function() {
s.volatile.emit('ev', 'data');
s.volatile.emit('ev', 'data');
}, 20);
}, 100);
});
var socket = client(srv, { transports: ['polling'] });
@@ -934,7 +1242,7 @@ describe('socket.io', function(){
setTimeout(function() {
expect(counter).to.be(1);
done();
}, 200);
}, 500);
});
it('should emit only one consecutive volatile event (ws)', function(done) {
@@ -1238,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);
@@ -1250,11 +1556,27 @@ 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 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){
expect(s.handshake.query.key1).to.be('aa');
expect(s.handshake.query.key2).to.be('&=bb');
done();
});
});
it('should handle very large json', function(done){
this.timeout(30000);
var srv = http();
var sio = io(srv);
var sio = io(srv, { perMessageDeflate: false });
var received = 0;
srv.listen(function(){
var socket = client(srv);
@@ -1279,8 +1601,9 @@ describe('socket.io', function(){
});
it('should handle very large binary data', function(done){
this.timeout(30000);
var srv = http();
var sio = io(srv);
var sio = io(srv, { perMessageDeflate: false });
var received = 0;
srv.listen(function(){
var socket = client(srv);
@@ -1320,16 +1643,45 @@ 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);
});
});
});
});
it('should enable compression by default', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv, '/chat');
sio.of('/chat').on('connection', function(s){
s.conn.once('packetCreate', function(packet) {
expect(packet.options.compress).to.be(true);
done();
});
sio.of('/chat').emit('woot', 'hi');
});
});
});
it('should disable compression', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv, '/chat');
sio.of('/chat').on('connection', function(s){
s.conn.once('packetCreate', function(packet) {
expect(packet.options.compress).to.be(false);
done();
});
sio.of('/chat').compress(false).emit('woot', 'hi');
});
});
});
it('should error with raw binary and warn', function(done){
var srv = http();
var sio = io(srv);
@@ -1363,6 +1715,55 @@ describe('socket.io', function(){
});
});
});
it('should handle empty binary packet', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv);
sio.on('connection', function(s){
s.once('error', function(err){
expect(err.message).to.match(/Illegal attachments/);
done();
});
s.conn.on('upgrade', function(){
socket.io.engine.write('5');
});
});
});
});
it('should not crash when messing with Object prototype', function(done){
Object.prototype.foo = 'bar';
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv);
sio.on('connection', function(s){
s.disconnect(true);
sio.close();
setTimeout(function(){
done();
}, 100);
});
});
});
it('should always trigger the callback (if provided) when joining a room', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv);
sio.on('connection', function(s){
s.join('a', function(){
s.join('a', done);
});
});
});
});
});
describe('messaging many', function(){
@@ -1627,15 +2028,15 @@ describe('socket.io', function(){
var socket = client(srv);
sio.on('connection', function(s){
s.join('a', function(){
expect(s.rooms).to.eql([s.id, 'a']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
s.join('b', function(){
expect(s.rooms).to.eql([s.id, 'a', 'b']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
s.join( 'c', function(){
expect(s.rooms).to.eql([s.id, 'a', 'b', 'c']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b', 'c']);
s.leave('b', function(){
expect(s.rooms).to.eql([s.id, 'a', 'c']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'c']);
s.leaveAll();
expect(s.rooms).to.eql([]);
expect(Object.keys(s.rooms)).to.eql([]);
done();
});
});
@@ -1671,13 +2072,13 @@ describe('socket.io', function(){
var socket = client(srv);
sio.on('connection', function(s){
s.join('a', function(){
expect(s.rooms).to.eql([s.id, 'a']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a']);
s.join('b', function(){
expect(s.rooms).to.eql([s.id, 'a', 'b']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
s.leave('unknown', function(){
expect(s.rooms).to.eql([s.id, 'a', 'b']);
expect(Object.keys(s.rooms)).to.eql([s.id, 'a', 'b']);
s.leaveAll();
expect(s.rooms).to.eql([]);
expect(Object.keys(s.rooms)).to.eql([]);
done();
});
});
@@ -1685,11 +2086,15 @@ describe('socket.io', function(){
});
});
});
});
describe('middleware', function(done){
var Socket = require('../lib/socket');
var Socket;
if (testVersion === 'compat') {
Socket = require('../dist/socket');
} else {
Socket = require('../lib/socket');
}
it('should call functions', function(done){
var srv = http();
@@ -1827,4 +2232,95 @@ 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 socket = client(srv, { multiplex: false });
socket.emit('join', 'woot');
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'));
});
socket.on('error', function(err){
expect(err).to.be('Authentication error');
done();
});
});
});
});
it('should pass `data` of error object', function(done){
var srv = http();
var sio = io(srv);
srv.listen(function(){
var socket = client(srv, { multiplex: false });
socket.emit('join', 'woot');
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'));
});
socket.on('error', function(err){
expect(err).to.eql({ a: 'b', c: 3 });
done();
});
});
});
});
});
});