Skip to content

Commit 0089ece

Browse files
committed
1.0.0 - rewrite to use streams2 and Buffers
1 parent 7f190aa commit 0089ece

13 files changed

Lines changed: 103 additions & 221 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
node_modules
2-
demo-bundle.js
2+
.DS_Store

binary-server.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

demo-server.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

demo.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

echo-server.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
21
var WebSocketServer = require('ws').Server
32
var http = require('http')
43
var websocket = require('./')
54
var server = null
6-
var fake = require('./fake-server')
7-
8-
var port = module.exports.port = fake.port
95

10-
module.exports.url = fake.url
6+
var port = module.exports.port = 8343
7+
var url = module.exports.url = 'ws://localhost:' + module.exports.port
118

129
module.exports.start = function(opts, cb) {
1310
if (server) {

fake-server.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

index.html

Lines changed: 0 additions & 10 deletions
This file was deleted.

index.js

Lines changed: 55 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,63 @@
1-
var through = require('through')
2-
var isBuffer = require('isbuffer')
3-
var WebSocketPoly = require('ws')
1+
var through = require('through2')
2+
var duplexify = require('duplexify')
3+
var WS = require('ws')
44

5-
function WebsocketStream(server, options) {
6-
if (!(this instanceof WebsocketStream)) return new WebsocketStream(server, options)
5+
module.exports = WebSocketStream
76

8-
this.stream = through(this.write.bind(this), this.end.bind(this))
9-
10-
this.stream.websocketStream = this
11-
this.options = options || {}
12-
this._buffer = []
13-
14-
if (typeof server === "object") {
15-
this.ws = server
16-
this.ws.on('message', this.onMessage.bind(this))
17-
this.ws.on('error', this.onError.bind(this))
18-
this.ws.on('close', this.onClose.bind(this))
19-
this.ws.on('open', this.onOpen.bind(this))
20-
if (this.ws.readyState === 1) this._open = true
7+
function WebSocketStream(target, options) {
8+
if (!options) options = {}
9+
var stream, socket
10+
var proxy = through(socketWrite, socketEnd)
11+
12+
// use existing WebSocket object that was passed in
13+
if (typeof target === 'object') {
14+
socket = target
15+
// otherwise make a new one
2116
} else {
22-
var opts = (process.title === 'browser') ? this.options.protocol : this.options
23-
this.ws = new WebSocketPoly(server, opts)
24-
this.ws.binaryType = this.options.binaryType || 'arraybuffer'
25-
this.ws.onmessage = this.onMessage.bind(this)
26-
this.ws.onerror = this.onError.bind(this)
27-
this.ws.onclose = this.onClose.bind(this)
28-
this.ws.onopen = this.onOpen.bind(this)
17+
socket = new WS(target, options)
18+
socket.binaryType = 'arraybuffer'
19+
}
20+
21+
// was already open when passed in
22+
if (socket.readyState === 1) {
23+
stream = proxy
24+
} else {
25+
stream = duplexify()
26+
socket.addEventListener("open", onready)
27+
}
28+
29+
socket.addEventListener("close", onclose)
30+
socket.addEventListener("error", onerror)
31+
socket.addEventListener("message", onmessage)
32+
33+
function socketWrite(chunk, enc, next) {
34+
socket.send(chunk)
35+
next()
2936
}
30-
31-
this.stream.destroy = this.destroy.bind(this)
32-
return this.stream
33-
}
34-
35-
module.exports = WebsocketStream
36-
module.exports.WebsocketStream = WebsocketStream
37-
38-
WebsocketStream.prototype.destroy = function() {
39-
this.ws.close()
40-
}
41-
42-
WebsocketStream.prototype.onMessage = function(e) {
43-
var data = e
44-
if (typeof data.data !== 'undefined') data = data.data
45-
46-
// type must be a Typed Array (ArrayBufferView)
47-
var type = this.options.type
48-
if (type && data instanceof ArrayBuffer) data = new type(data)
4937

50-
this.stream.queue(data)
51-
}
52-
53-
WebsocketStream.prototype.onError = function(err) {
54-
this.stream.emit('error', err)
55-
}
56-
57-
WebsocketStream.prototype.onClose = function(err) {
58-
if (this._destroy) return
59-
this.stream.emit('end')
60-
this.stream.emit('close')
61-
}
62-
63-
WebsocketStream.prototype.onOpen = function(err) {
64-
if (this._destroy) return
65-
this._open = true
66-
for (var i = 0; i < this._buffer.length; i++) {
67-
this._write(this._buffer[i])
38+
function socketEnd(done) {
39+
socket.close()
40+
done()
6841
}
69-
this._buffer = undefined
70-
this.stream.emit('open')
71-
this.stream.emit('connect')
72-
if (this._end) this.ws.close()
73-
}
74-
75-
WebsocketStream.prototype.write = function(data) {
76-
if (!this._open) {
77-
this._buffer.push(data)
78-
} else {
79-
this._write(data)
42+
43+
function onready() {
44+
stream.setReadable(proxy)
45+
stream.setWritable(proxy)
8046
}
81-
}
82-
83-
WebsocketStream.prototype._write = function(data) {
84-
if (this.ws.readyState == 1)
85-
// we are connected
86-
typeof WebSocket != 'undefined' && this.ws instanceof WebSocket
87-
? this.ws.send(data)
88-
: this.ws.send(data, { binary : isBuffer(data) })
89-
else
90-
this.stream.emit('error', 'Not connected')
91-
}
92-
93-
WebsocketStream.prototype.end = function(data) {
94-
if (data !== undefined) this.stream.queue(data)
95-
if (this._open) this.ws.close()
96-
this._end = true
47+
48+
function onclose() {
49+
stream.destroy()
50+
}
51+
52+
function onerror(err) {
53+
stream.destroy(err)
54+
}
55+
56+
function onmessage(event) {
57+
var data = event.data
58+
if (data instanceof ArrayBuffer) data = new Buffer(new Uint8Array(data))
59+
proxy.push(data)
60+
}
61+
62+
return stream
9763
}

package.json

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
{
22
"name": "websocket-stream",
3-
"version": "0.6.0",
4-
"description": "websockets with the node stream api. works in browser and node",
3+
"version": "1.0.0",
4+
"description": "Use websockets with the node streams API. Works in browser and node",
55
"scripts": {
6-
"start": "browserify demo.js -o demo-bundle.js && node demo-server.js",
76
"test": "node test.js",
8-
"echo": "node echo-server.js"
7+
"start": "beefy test-client.js"
98
},
109
"repository": {
1110
"type": "git",
@@ -23,35 +22,18 @@
2322
"email": "max@maxogden.com"
2423
},
2524
"dependencies": {
26-
"isbuffer": "0.0.0",
27-
"ws": "~0.4.30",
28-
"through": "~2.3.4"
25+
"duplexify": "^3.2.0",
26+
"through2": "^0.6.1",
27+
"ws": "^0.4.32",
28+
"xtend": "^4.0.0"
2929
},
3030
"devDependencies": {
31-
"el-streamo": "1.0.0",
32-
"ecstatic": "0.4.2",
33-
"browserify": "2.14.1",
34-
"stringstream": "0.0.4",
35-
"tape": "~1.0.4"
31+
"beefy": "^2.1.1",
32+
"browserify": "^5.11.1",
33+
"tape": "^2.14.0"
3634
},
3735
"optionalDependencies": {},
38-
"engines": {
39-
"node": ">=0.8"
40-
},
4136
"browser": {
4237
"./echo-server.js": "./fake-server.js"
43-
},
44-
"testling": {
45-
"files": "test.js",
46-
"server": "node echo-server.js",
47-
"browsers": [
48-
"ie/6..latest",
49-
"chrome/20..latest",
50-
"firefox/10..latest",
51-
"safari/latest",
52-
"opera/11.0..latest",
53-
"iphone/6",
54-
"ipad/6"
55-
]
5638
}
5739
}

readme.md

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,24 @@
11
# websocket-stream
22

3-
npm install websocket-stream
3+
[![NPM](https://nodei.co/npm/websocket-stream.png?global=true)](https://nodei.co/npm/websocket-stream/)
44

5-
use HTML5 [websockets](https://developer.mozilla.org/en-US/docs/WebSockets) the node way -- with streams
5+
Use HTML5 [websockets](https://developer.mozilla.org/en-US/docs/WebSockets) using the Node Streams API. Works in Node or in Browsers.
66

7-
# in the browser
7+
### In the browser
88

9-
you can use [browserify](https://github.com/substack/node-browserify) to package this module for browser use.
9+
You can use [browserify](https://github.com/substack/node-browserify) to package this module for browser use.
1010

1111
```javascript
1212
var websocket = require('websocket-stream')
1313
var ws = websocket('ws://realtimecats.com')
1414
ws.pipe(somewhereAwesome)
1515
```
1616

17-
`ws` is a stream and speaks stream events: `data`, `error` and `end`. that means you can pipe output to anything that accepts streams. you can also pipe data into streams (such as a webcam feed or audio data)
17+
In the example above `ws` is a duplex stream. That means you can pipe output to anything that accepts streams. You can also pipe data into streams (such as a webcam feed or audio data).
1818

19-
### browserify steps
20-
```javascript
21-
npm install -g browserify // install browserify
22-
cd node_modules/websocket-stream
23-
npm install . // install dev dependencies
24-
browserify index.js -s websocket-stream > websocket-stream.js // require websocket-stream.js in your client-side app
25-
```
26-
27-
# on the server
19+
### On the server
2820

29-
using the [`ws`](http://npmjs.org/ws) module you can make a websocket server and use this module to get websocket streams on the server:
21+
Using the [`ws`](http://npmjs.org/ws) module you can make a websocket server and use this module to get websocket streams on the server:
3022

3123
```javascript
3224
var WebSocketServer = require('ws').Server
@@ -38,31 +30,20 @@ wss.on('connection', function(ws) {
3830
})
3931
```
4032

41-
## options
33+
## run the tests
4234

43-
pass in options as the second argument like this:
35+
### server-side tests
4436

45-
```js
46-
websocketStream('ws://foobar', { type: someTypedArray })
47-
48-
// e.g. {type: Uint8Array} means you'll get Uint8Arrays back instead of ArrayBuffers
4937
```
38+
npm test
5039
51-
possible options are...
52-
53-
```js
54-
{
55-
protocol: // optional, string, specify websocket protocol
56-
type: // optional, TypedArray object, wraps the ArrayBuffer before emitting
57-
}
5840
```
5941

60-
### binary sockets
42+
### client side tests
6143

62-
To send binary data just write a [Buffer](nodejs.org/api/buffer.html) or [TypedArray](https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays) to the stream.
63-
On the other end you will receive [Buffer](nodejs.org/api/buffer.html) instances if it's the server and [ArrayBuffer](https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/ArrayBuffer) instances if it's the client. The client will default to `ArrayBuffer` objects but can also be configured to receive `Blob`s.
44+
first start the echo server by running `node test-server.js`
6445

65-
If you write binary data to a websocket on the server, the client will receive binary objects. Same thing goes for strings.
46+
then run `npm start` and open `localhost:9966` in your browser and open the Dev Tools console to see test output
6647

6748
## license
6849

0 commit comments

Comments
 (0)