Comparing version 0.4.0 to 0.4.1
@@ -0,1 +1,12 @@ | ||
v0.4.1 - Jan 25th 2012 | ||
===================== | ||
* Use readline in wscat [tricknotes] | ||
* Refactor _state away, in favor of the new _readyState [tricknotes] | ||
* travis-ci integration [einaros] | ||
* Fixed race condition in testsuite, causing a few tests to fail (without actually indicating errors) on travis [einaros] | ||
* Expose pong event [paddybyers] | ||
* Enabled running of WebSocketServer in noServer-mode, meaning that upgrades are passed in manually. [einaros] | ||
* Reworked connection procedure for WebSocketServer, and cleaned up tests. [einaros] | ||
v0.4.0 - Jan 2nd 2012 | ||
@@ -2,0 +13,0 @@ ===================== |
@@ -30,2 +30,3 @@ /*! | ||
function WebSocket(address, options) { | ||
var self = this; | ||
if (Object.prototype.toString.call(address) == '[object Array]') { | ||
@@ -57,9 +58,4 @@ /** | ||
}); | ||
Object.defineProperty(this, '_state', { writable: true, value: 'connecting' }); | ||
Object.defineProperty(this, '_isServer', { writable: true, value: true }); | ||
var self = this; | ||
process.nextTick(function() { | ||
upgrade.apply(self, address); | ||
}); | ||
Object.defineProperty(this, '_readyState', { writable: true, value: WebSocket.CONNECTING }); | ||
Object.defineProperty(this, '_isServer', { writable: false, value: true }); | ||
} | ||
@@ -71,3 +67,3 @@ else { | ||
Object.defineProperty(this, '_isServer', { writable: true, value: false }); | ||
Object.defineProperty(this, '_isServer', { writable: false, value: false }); | ||
@@ -77,3 +73,3 @@ var serverUrl = url.parse(address); | ||
var httpObj = (serverUrl.protocol === 'wss:' || serverUrl.protocol === 'https:') ? https : http; | ||
Object.defineProperty(this, 'url', { | ||
@@ -135,3 +131,2 @@ writable: false, | ||
var req = httpObj.request(requestOptions); | ||
var self = this; | ||
(isNodeV4 ? agent : req).on('error', function(error) { | ||
@@ -141,4 +136,4 @@ self.emit('error', error); | ||
(isNodeV4 ? agent : req).on('upgrade', function(res, socket, upgradeHead) { | ||
if (self._state == 'disconnected') { | ||
// client disconnected before server accepted connection | ||
if (self.readyState == WebSocket.CLOSED) { | ||
// client closed before server accepted connection | ||
self.emit('close'); | ||
@@ -159,3 +154,3 @@ socket.end(); | ||
req.end(); | ||
Object.defineProperty(this, '_state', { writable: true, value: 'connecting' }); | ||
Object.defineProperty(this, '_readyState', { writable: true, value: WebSocket.CONNECTING }); | ||
} | ||
@@ -171,14 +166,9 @@ | ||
get: function() { | ||
switch(this._state) { | ||
case 'connecting': | ||
return WebSocket.CONNECTING; | ||
case 'connected': | ||
return WebSocket.OPEN; | ||
case 'closing': | ||
return WebSocket.CLOSING; | ||
case 'disconnected': | ||
return WebSocket.CLOSED; | ||
} | ||
return this._readyState; | ||
} | ||
}); | ||
if (this._isServer) { | ||
upgrade.apply(this, address); | ||
} | ||
} | ||
@@ -218,10 +208,10 @@ | ||
WebSocket.prototype.close = function(code, data) { | ||
if (this._state == 'closing') return; | ||
if (this._state == 'connecting') { | ||
this._state = 'disconnected'; | ||
if (this.readyState == WebSocket.CLOSING) return; | ||
if (this.readyState == WebSocket.CONNECTING) { | ||
this._readyState = WebSocket.CLOSED; | ||
return; | ||
} | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); | ||
try { | ||
this._state = 'closing'; | ||
this._readyState = WebSocket.CLOSING; | ||
this._closeCode = code; | ||
@@ -247,3 +237,3 @@ this._closeMessage = data; | ||
WebSocket.prototype.ping = function(data, options) { | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); | ||
options = options || {}; | ||
@@ -263,3 +253,3 @@ if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
WebSocket.prototype.pong = function(data, options) { | ||
if (this._state != 'connected') throw new Error('not connected'); | ||
if (this.readyState != WebSocket.OPEN) throw new Error('not opened'); | ||
options = options || {}; | ||
@@ -284,5 +274,5 @@ if (typeof options.mask == 'undefined') options.mask = !this._isServer; | ||
} | ||
if (this._state != 'connected') { | ||
if (typeof cb == 'function') cb(new Error('not connected')); | ||
else throw new Error('not connected'); | ||
if (this.readyState != WebSocket.OPEN) { | ||
if (typeof cb == 'function') cb(new Error('not opened')); | ||
else throw new Error('not opened'); | ||
return; | ||
@@ -324,5 +314,5 @@ } | ||
if (typeof cb != 'function') throw new Error('callback must be provided'); | ||
if (this._state != 'connected') { | ||
if (typeof cb == 'function') cb(new Error('not connected')); | ||
else throw new Error('not connected'); | ||
if (this.readyState != WebSocket.OPEN) { | ||
if (typeof cb == 'function') cb(new Error('not opened')); | ||
else throw new Error('not opened'); | ||
return; | ||
@@ -341,3 +331,3 @@ } | ||
try { | ||
if (self._state != 'connected') throw new Error('not connected'); | ||
if (self.readyState != WebSocket.OPEN) throw new Error('not opened'); | ||
options.fin = final === true; | ||
@@ -367,4 +357,4 @@ self._sender.send(data, options); | ||
} | ||
else if (this._state == 'connecting') { | ||
this._state = 'disconnected'; | ||
else if (this.readyState == WebSocket.CONNECTING) { | ||
this._readyState = WebSocket.CLOSED; | ||
} | ||
@@ -437,9 +427,9 @@ }; | ||
socket.on('end', function() { | ||
if (self._state == 'disconnected') return; | ||
self._state = 'disconnected'; | ||
if (self.readyState == WebSocket.CLOSED) return; | ||
self._readyState = WebSocket.CLOSED; | ||
self.emit('close', self._closeCode || 1000, self._closeMessage || ''); | ||
}); | ||
socket.on('close', function() { | ||
if (self._state == 'disconnected') return; | ||
self._state = 'disconnected'; | ||
if (self.readyState == WebSocket.CLOSED) return; | ||
self._readyState = WebSocket.CLOSED; | ||
self.emit('close', self._closeCode || 1000, self._closeMessage || ''); | ||
@@ -466,2 +456,5 @@ }); | ||
}); | ||
receiver.on('pong', function(data, flags) { | ||
self.emit('pong', data, flags); | ||
}); | ||
receiver.on('close', function(code, data, flags) { | ||
@@ -483,3 +476,3 @@ flags = flags || {}; | ||
}); | ||
this._state = 'connected'; | ||
this._readyState = WebSocket.OPEN; | ||
this.emit('open'); | ||
@@ -505,5 +498,5 @@ | ||
stream.on('data', function(data) { | ||
if (instance._state != 'connected') { | ||
if (typeof cb == 'function') cb(new Error('not connected')); | ||
else instance.emit('error', new Error('not connected')); | ||
if (instance.readyState != WebSocket.OPEN) { | ||
if (typeof cb == 'function') cb(new Error('not opened')); | ||
else instance.emit('error', new Error('not opened')); | ||
return; | ||
@@ -515,5 +508,5 @@ } | ||
stream.on('end', function() { | ||
if (instance._state != 'connected') { | ||
if (typeof cb == 'function') cb(new Error('not connected')); | ||
else instance.emit('error', new Error('not connected')); | ||
if (instance.readyState != WebSocket.OPEN) { | ||
if (typeof cb == 'function') cb(new Error('not opened')); | ||
else instance.emit('error', new Error('not opened')); | ||
return; | ||
@@ -520,0 +513,0 @@ } |
@@ -26,9 +26,12 @@ /*! | ||
verifyOrigin: null, | ||
path: null | ||
path: null, | ||
noServer: false | ||
}).merge(options); | ||
if (!options.value.port && !options.value.server) { | ||
if (!options.value.port && !options.value.server && !options.value.noServer) { | ||
throw new TypeError('`port` or a `server` must be provided'); | ||
} | ||
if (!options.value.server) { | ||
var self = this; | ||
if (options.value.port) { | ||
Object.defineProperty(this, '_server', { | ||
@@ -43,6 +46,6 @@ configurable: true, | ||
Object.defineProperty(this, '_closeServer', { | ||
value: function() { this._server.close(); } | ||
value: function() { self._server.close(); } | ||
}); | ||
} | ||
else { | ||
else if (options.value.server) { | ||
Object.defineProperty(this, '_server', { value: options.value.server, configurable: true }); | ||
@@ -55,3 +58,3 @@ if (options.value.path) { | ||
} | ||
if (typeof this._server._webSocketPaths !== 'object') { | ||
if (typeof this._server._webSocketPaths !== 'object') { | ||
Object.defineProperty(this._server, '_webSocketPaths', { value: {}, configurable: true }); | ||
@@ -63,89 +66,16 @@ } | ||
Object.defineProperty(this, 'path', { value: options.value.path }); | ||
Object.defineProperty(this, '_clients', { value: [] }); | ||
var self = this; | ||
this._server.on('error', function(error) { | ||
self.emit('error', error) | ||
}); | ||
this._server.on('upgrade', function(req, socket, upgradeHead) { | ||
// check for wrong path | ||
if (options.value.path) { | ||
var u = url.parse(req.url); | ||
if (u && u.pathname !== options.value.path) return; | ||
} | ||
if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify key presence | ||
if (!req.headers['sec-websocket-key']) { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify version | ||
var version = parseInt(req.headers['sec-websocket-version']); | ||
if ([8, 13].indexOf(version) === -1) { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify origin | ||
var origin = version < 13 ? | ||
req.headers['sec-websocket-origin'] : | ||
req.headers['origin']; | ||
if (typeof options.value.verifyOrigin == 'function') { | ||
if (!options.value.verifyOrigin(origin)) { | ||
abortConnection(socket, 401, 'Unauthorized'); | ||
return; | ||
} | ||
} | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
// calc key | ||
var key = req.headers['sec-websocket-key']; | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); | ||
key = shasum.digest('base64'); | ||
var headers = [ | ||
'HTTP/1.1 101 Switching Protocols' | ||
, 'Upgrade: websocket' | ||
, 'Connection: Upgrade' | ||
, 'Sec-WebSocket-Accept: ' + key | ||
]; | ||
if (typeof protocol != 'undefined') { | ||
headers['Sec-WebSocket-Protocol'] = protocol; | ||
} | ||
try { | ||
socket.write(headers.concat('', '').join('\r\n')); | ||
} | ||
catch (e) { | ||
try { socket.end(); } catch (_) {} | ||
return; | ||
} | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
var client = new WebSocket(Array.prototype.slice.call(arguments, 0), { | ||
protocolVersion: version, | ||
protocol: protocol | ||
if (typeof this._server != 'undefined') { | ||
this._server.on('error', function(error) { | ||
self.emit('error', error) | ||
}); | ||
self._clients.push(client); | ||
client.on('open', function() { | ||
self.emit('connection', client); | ||
this._server.on('upgrade', function(req, socket, upgradeHead) { | ||
var client = self.handleUpgrade(req, socket, upgradeHead); | ||
if (client) self.emit('connection', client); | ||
}); | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
}); | ||
Object.defineProperty(this, 'clients', { | ||
} | ||
Object.defineProperty(this, 'options', { value: options.value }); | ||
Object.defineProperty(this, 'path', { value: options.value.path }); | ||
Object.defineProperty(this, '_clients', { value: [] }); | ||
Object.defineProperty(this, 'clients', { | ||
get: function() { return self._clients; } | ||
@@ -178,3 +108,3 @@ }); | ||
} | ||
// remove path descriptor, if any | ||
@@ -187,3 +117,3 @@ if (this.path && this._server._webSocketPaths) { | ||
} | ||
// close the http server if it was internally created | ||
@@ -201,2 +131,79 @@ try { | ||
WebSocketServer.prototype.handleUpgrade = function(req, socket, upgradeHead) { | ||
// check for wrong path | ||
if (this.options.path) { | ||
var u = url.parse(req.url); | ||
if (u && u.pathname !== this.options.path) return; | ||
} | ||
if (typeof req.headers.upgrade === 'undefined' || req.headers.upgrade.toLowerCase() !== 'websocket') { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify key presence | ||
if (!req.headers['sec-websocket-key']) { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify version | ||
var version = parseInt(req.headers['sec-websocket-version']); | ||
if ([8, 13].indexOf(version) === -1) { | ||
abortConnection(socket, 400, 'Bad Request'); | ||
return; | ||
} | ||
// verify origin | ||
var origin = version < 13 ? | ||
req.headers['sec-websocket-origin'] : | ||
req.headers['origin']; | ||
if (typeof this.options.verifyOrigin == 'function') { | ||
if (!this.options.verifyOrigin(origin)) { | ||
abortConnection(socket, 401, 'Unauthorized'); | ||
return; | ||
} | ||
} | ||
var protocol = req.headers['sec-websocket-protocol']; | ||
// calc key | ||
var key = req.headers['sec-websocket-key']; | ||
var shasum = crypto.createHash('sha1'); | ||
shasum.update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); | ||
key = shasum.digest('base64'); | ||
var headers = [ | ||
'HTTP/1.1 101 Switching Protocols' | ||
, 'Upgrade: websocket' | ||
, 'Connection: Upgrade' | ||
, 'Sec-WebSocket-Accept: ' + key | ||
]; | ||
if (typeof protocol != 'undefined') { | ||
headers['Sec-WebSocket-Protocol'] = protocol; | ||
} | ||
try { | ||
socket.write(headers.concat('', '').join('\r\n')); | ||
} | ||
catch (e) { | ||
try { socket.end(); } catch (_) {} | ||
return; | ||
} | ||
socket.setTimeout(0); | ||
socket.setNoDelay(true); | ||
var client = new WebSocket(Array.prototype.slice.call(arguments, 0), { | ||
protocolVersion: version, | ||
protocol: protocol | ||
}); | ||
this._clients.push(client); | ||
var self = this; | ||
client.on('close', function() { | ||
var index = self._clients.indexOf(client); | ||
if (index != -1) { | ||
self._clients.splice(index, 1); | ||
} | ||
}); | ||
return client; | ||
} | ||
module.exports = WebSocketServer; | ||
@@ -203,0 +210,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"description": "simple and very fast websocket protocol client for node.js", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
@@ -0,5 +1,9 @@ | ||
[![Build Status](https://secure.travis-ci.org/einaros/ws.png)](http://travis-ci.org/einaros/ws) | ||
# ws: a node.js websocket implementation # | ||
`ws` is a simple to use, blazing fast, websocket implementation for node.js, up-to-date against RFC-6455. | ||
`ws` is a simple to use websocket implementation, up-to-date against RFC-6455. | ||
It is probably also the fastest websocket library running on node.js (http://hobbycoding.posterous.com/the-fastest-websocket-module-for-nodejs). | ||
Passes the quite extensible Autobahn test suite. See http://einaros.github.com/ws for the full reports. | ||
@@ -50,2 +54,15 @@ | ||
### Server example ### | ||
```js | ||
var WebSocketServer = require('ws').Server | ||
, wss = new WebSocketServer({port: 8080}); | ||
wss.on('connection', function(ws) { | ||
ws.on('message', function(message) { | ||
console.log('received: %s', message); | ||
}); | ||
ws.send('something'); | ||
}); | ||
``` | ||
### echo.websocket.org demo ### | ||
@@ -52,0 +69,0 @@ |
@@ -1,3 +0,2 @@ | ||
var assert = require('assert') | ||
, Sender = require('../lib/Sender'); | ||
var Sender = require('../lib/Sender'); | ||
require('should'); | ||
@@ -4,0 +3,0 @@ |
@@ -1,3 +0,2 @@ | ||
var assert = require('assert') | ||
, Validation = require('../lib/Validation').Validation; | ||
var Validation = require('../lib/Validation').Validation; | ||
require('should'); | ||
@@ -4,0 +3,0 @@ |
@@ -67,3 +67,3 @@ var assert = require('assert') | ||
it('set to connected once connection is established', function(done) { | ||
it('set to open once connection is established', function(done) { | ||
server.createServer(++port, function(srv) { | ||
@@ -124,5 +124,32 @@ var ws = new WebSocket('ws://localhost:' + port); | ||
it('can disconnect before connection is established', function(done) { | ||
server.createServer(++port, function(srv) { | ||
describe('events', function() { | ||
it('emits a ping event', function(done) { | ||
var wss = new WebSocketServer({port: ++port}); | ||
wss.on('connection', function(client) { | ||
client.ping(); | ||
}); | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('ping', function() { | ||
ws.terminate(); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
it('emits a pong event', function(done) { | ||
var wss = new WebSocketServer({port: ++port}); | ||
wss.on('connection', function(client) { | ||
client.pong(); | ||
}); | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('pong', function() { | ||
ws.terminate(); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('can disconnect before connection is established', function(done) {server.createServer(++port, function(srv) { | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.terminate(); | ||
@@ -129,0 +156,0 @@ ws.on('open', function() { |
@@ -1,3 +0,2 @@ | ||
var assert = require('assert') | ||
, http = require('http') | ||
var http = require('http') | ||
, WebSocket = require('../') | ||
@@ -51,2 +50,13 @@ , WebSocketServer = WebSocket.Server | ||
it('does not throw an error if no port or server is specified, when the noServer option is true', function() { | ||
var gotException = false; | ||
try { | ||
var wss = new WebSocketServer({noServer: true}); | ||
} | ||
catch (e) { | ||
gotException = true; | ||
} | ||
gotException.should.eql(false); | ||
}); | ||
it('emits an error if http server bind fails', function(done) { | ||
@@ -57,8 +67,2 @@ var wss = new WebSocketServer({port: 1}); | ||
it('uses passed server object', function () { | ||
var srv = http.createServer() | ||
, wss = new WebSocketServer({server: srv}); | ||
wss._server.should.equal(srv); | ||
}); | ||
it('starts a server on a given port', function(done) { | ||
@@ -74,3 +78,3 @@ var wss = new WebSocketServer({port: ++port}, function() { | ||
it('works with a precreated http server', function (done) { | ||
it('uses a precreated http server', function (done) { | ||
var srv = http.createServer(); | ||
@@ -83,2 +87,3 @@ srv.listen(++port, function () { | ||
wss.close(); | ||
srv.close(); | ||
done(); | ||
@@ -113,4 +118,4 @@ }); | ||
}); | ||
it('cannot have two different instances listening on the same http server with two different paths', function(done) { | ||
it('cannot have two different instances listening on the same http server with the same path', function(done) { | ||
var srv = http.createServer(); | ||
@@ -120,5 +125,7 @@ srv.listen(++port, function () { | ||
try { | ||
var wss2 = new WebSocketServer({server: srv, path: '/wss1'}); | ||
var wss2 = new WebSocketServer({server: srv, path: '/wss1'}); | ||
} | ||
catch (e) { | ||
wss1.close(); | ||
srv.close(); | ||
done(); | ||
@@ -146,3 +153,3 @@ } | ||
}); | ||
it('does not close a precreated server', function(done) { | ||
@@ -183,120 +190,122 @@ var srv = http.createServer(); | ||
it('does not accept connections with no sec-websocket-key', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
describe('connection establishing', function() { | ||
it('does not accept connections with no sec-websocket-key', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
it('does not accept connections with no sec-websocket-version', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
it('does not accept connections with no sec-websocket-version', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
it('does not accept connections with invalid sec-websocket-version', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 12 | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
it('does not accept connections with invalid sec-websocket-version', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 12 | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(400); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
it('does not accept connections with invalid sec-websocket-origin (8)', function(done) { | ||
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { | ||
o.should.eql('http://foobar.com'); | ||
return false; | ||
}}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 8, | ||
'Sec-WebSocket-Origin': 'http://foobar.com' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(401); | ||
wss.close(); | ||
done(); | ||
it('does not accept connections with invalid sec-websocket-origin (8)', function(done) { | ||
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { | ||
o.should.eql('http://foobar.com'); | ||
return false; | ||
}}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 8, | ||
'Sec-WebSocket-Origin': 'http://foobar.com' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(401); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
it('does not accept connections with invalid origin', function(done) { | ||
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { | ||
o.should.eql('http://foobar.com'); | ||
return false; | ||
}}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 13, | ||
'Origin': 'http://foobar.com' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(401); | ||
wss.close(); | ||
done(); | ||
it('does not accept connections with invalid origin', function(done) { | ||
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { | ||
o.should.eql('http://foobar.com'); | ||
return false; | ||
}}, function() { | ||
var options = { | ||
port: port, | ||
host: '127.0.0.1', | ||
headers: { | ||
'Connection': 'Upgrade', | ||
'Upgrade': 'websocket', | ||
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', | ||
'Sec-WebSocket-Version': 13, | ||
'Origin': 'http://foobar.com' | ||
} | ||
}; | ||
var req = http.request(options); | ||
req.end(); | ||
req.on('response', function(res) { | ||
res.statusCode.should.eql(401); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
wss.on('error', function() {}); | ||
}); | ||
@@ -318,3 +327,3 @@ | ||
describe('properties', function() { | ||
describe('client properties', function() { | ||
it('protocol is exposed', function(done) { | ||
@@ -366,3 +375,3 @@ var wss = new WebSocketServer({port: ++port}, function() { | ||
}); | ||
it('is updated when client terminates the connection', function(done) { | ||
@@ -382,3 +391,3 @@ var ws; | ||
}); | ||
it('is updated when client closes the connection', function(done) { | ||
@@ -399,3 +408,33 @@ var ws; | ||
}); | ||
describe('#options', function() { | ||
it('exposes options passed to constructor', function(done) { | ||
var wss = new WebSocketServer({port: ++port}, function() { | ||
wss.options.port.should.eql(port); | ||
wss.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('#handleUpgrade', function() { | ||
it('can be used for a pre-existing server', function (done) { | ||
var srv = http.createServer(); | ||
srv.listen(++port, function () { | ||
var wss = new WebSocketServer({noServer: true}); | ||
srv.on('upgrade', function(req, socket, upgradeHead) { | ||
var client = wss.handleUpgrade(req, socket, upgradeHead); | ||
client.send('hello'); | ||
}); | ||
var ws = new WebSocket('ws://localhost:' + port); | ||
ws.on('message', function(message) { | ||
message.should.eql('hello'); | ||
wss.close(); | ||
srv.close(); | ||
done(); | ||
}) | ||
}); | ||
}); | ||
}); | ||
}); | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
157328
39
3983
136