Comparing version 0.2.1 to 0.2.2
{ | ||
"name": "koa-ws", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "koa", |
@@ -17,3 +17,3 @@ (function(){ | ||
try { | ||
debug = require('debug')('koa-ws'); | ||
debug = require('debug')('koa-ws:client'); | ||
} catch (e) { | ||
@@ -90,3 +90,3 @@ debug = console.log.bind(console); | ||
if (payload.method) { | ||
var request = new Request(this, payload); | ||
var request = new Request(this.socket, payload); | ||
if (typeof this._methods[payload.method] === 'undefined') { | ||
@@ -101,3 +101,3 @@ debug('← (%s) Missing handler', payload.method); | ||
} else { | ||
debug('← (%s) %o', payload.method, payload.params); | ||
debug('← (%s) %s: %o', payload.id, payload.method, payload.params); | ||
this._methods[payload.method].apply( | ||
@@ -193,3 +193,3 @@ request, | ||
try { | ||
debug('→ %o', payload); | ||
debug('→ (%s) %s: %o', payload.id, payload.method, payload.params); | ||
this.socket.send(JSON.stringify(payload)); | ||
@@ -196,0 +196,0 @@ } catch (e) { |
@@ -13,3 +13,3 @@ var debug = require('debug')('koa-ws:request'); | ||
try { | ||
var data = { | ||
var payload = { | ||
jsonrpc: '2.0', | ||
@@ -22,4 +22,4 @@ error: { | ||
}; | ||
debug('→', data); | ||
this.socket.send(JSON.stringify(data)); | ||
debug('→ Error %s: %o', payload.error.code, payload.error.message); | ||
this.socket.send(JSON.stringify(payload)); | ||
} catch (e) { | ||
@@ -37,3 +37,3 @@ console.error('Something went wrong: ', e.stack); | ||
}; | ||
debug('→ result for id %s: %o', payload.id, payload.result); | ||
debug('→ (%s) Result: %o', payload.id, payload.result); | ||
this.socket.send(JSON.stringify(payload)); | ||
@@ -40,0 +40,0 @@ } catch (e) { |
@@ -21,9 +21,12 @@ var co = require('co'); | ||
// Container for methods | ||
this.methods = {}; | ||
this._methods = {}; | ||
// Container for sockets | ||
this.sockets = {}; | ||
this._sockets = {}; | ||
// Session to socket mapping | ||
this.sessions = {}; | ||
this._sessions = {}; | ||
// Callback container for results | ||
this._awaitingResults = {}; | ||
} | ||
@@ -46,22 +49,42 @@ | ||
KoaWebSocketServer.prototype.onConnection = function (socket) { | ||
var server = this.server; | ||
var methods = this.methods; | ||
var sockets = this.sockets; | ||
var sessions = this.sessions; | ||
var server = this._server; | ||
var methods = this._methods; | ||
var sockets = this._sockets; | ||
var sessions = this._sessions; | ||
var awaitingResults = {}; | ||
socket.method = function (method, params) { | ||
socket.method = function () { | ||
var cb = null; | ||
var payload = { | ||
jsonrpc: '2.0', | ||
method: arguments[0], | ||
id: Math.random().toString(36).substr(2, 9) // Generate random id | ||
}; | ||
if (typeof arguments[1] !== 'function' && typeof arguments[1] !== 'undefined') { | ||
payload.params = arguments[1]; | ||
if (typeof arguments[2] === 'function') { | ||
cb = arguments[2]; | ||
} | ||
} else if (typeof arguments[1] === 'function') { | ||
cb = arguments[1]; | ||
} | ||
if (cb) { | ||
this._awaitingResults[payload.id] = function () { | ||
cb.apply(this, arguments); | ||
delete this._awaitingResults[payload.id]; | ||
}.bind(this); | ||
} | ||
try { | ||
var payload = { | ||
jsonrpc: '2.0', | ||
method: method | ||
}; | ||
if (params) { | ||
payload.params = params; | ||
} | ||
debug('→ %s: %o', payload.method, payload.params); | ||
debug('→ (%s) %s: %o', payload.id, payload.method, payload.params); | ||
socket.send(JSON.stringify(payload)); | ||
} catch (e) { | ||
console.error('Something went wrong: ', e.stack); | ||
if (cb) { | ||
cb.call(this, e); | ||
} | ||
} | ||
}; | ||
}.bind(this); | ||
@@ -75,3 +98,3 @@ socket.result = function (result) { | ||
}; | ||
debug('→ result for id %s: %o', payload.id, payload.result); | ||
debug('→ (%s) Result: %o', payload.id, payload.result); | ||
socket.send(JSON.stringify(payload)); | ||
@@ -81,7 +104,7 @@ } catch (e) { | ||
} | ||
} | ||
}.bind(this) | ||
socket.error = function (code, message) { | ||
try { | ||
var data = { | ||
var payload = { | ||
jsonrpc: '2.0', | ||
@@ -94,4 +117,8 @@ error: { | ||
}; | ||
debug('→', data); | ||
socket.send(JSON.stringify(data)); | ||
if (payload.id) { | ||
debug('→ (%s) Error %s: %s', payload.id, payload.error.code, payload.error.message); | ||
} else { | ||
debug('→ Error %s: %s', payload.id, payload.error.code, payload.error.message); | ||
} | ||
socket.send(JSON.stringify(payload)); | ||
} catch (e) { | ||
@@ -129,9 +156,9 @@ console.error('Something went wrong: ', e.stack); | ||
debug('Wrong protocol: %s', payload.jsonrpc); | ||
socket.error.apply(request, [-32600, 'Invalid Request']); | ||
socket.error.apply(request, [-32600, 'Invalid request']); | ||
return; | ||
} | ||
if (!payload.method) { | ||
if (!payload.method && (!payload.result && !payload.id)) { | ||
debug('Missing method: %o', payload); | ||
socket.error.apply(request, [-32600, 'Invalid Request']); | ||
socket.error.apply(request, [-32600, 'Invalid request']); | ||
return; | ||
@@ -146,16 +173,27 @@ } | ||
debug('← %s: %o', payload.method, payload.params); | ||
if (typeof methods[payload.method] === 'function') { | ||
try { | ||
methods[payload.method].apply(request); | ||
} catch (e) { | ||
debug('Internal error: %s', e.stack); | ||
socket.error.apply(request, [-32603, 'Internal error']); | ||
if (payload.id && payload.error) { | ||
debug('← (%s) Error %s: %o', payload.id, payload.error.code, payload.error.message); | ||
if (typeof this._awaitingResults[payload.id] === 'function') { | ||
this._awaitingResults[payload.id].apply(this, [payload.error]); | ||
} | ||
} else if (payload.id && payload.result) { | ||
debug('← (%s) Result: %o', payload.id, payload.result); | ||
if (typeof this._awaitingResults[payload.id] === 'function') { | ||
this._awaitingResults[payload.id].apply(this, [null, payload.result]); | ||
} | ||
} else { | ||
debug('Method not found: %s', payload.method, payload.params); | ||
socket.error.apply(request, [-32601, 'Method not found']); | ||
debug('← (%s) %s: %o', payload.id, payload.method, payload.params); | ||
if (typeof methods[payload.method] === 'function') { | ||
try { | ||
methods[payload.method].apply(request); | ||
} catch (e) { | ||
debug('Internal error: %s', e.stack); | ||
socket.error.apply(request, [-32603, 'Internal error']); | ||
} | ||
} else { | ||
debug('Method not found: %s', payload.method, payload.params); | ||
socket.error.apply(request, [-32601, 'Method not found']); | ||
} | ||
} | ||
}); | ||
}.bind(this)); | ||
@@ -198,3 +236,3 @@ // Let's try and connect the socket to session | ||
generator.expose = expose || false; | ||
this.methods[method] = co(generator); | ||
this._methods[method] = co(generator); | ||
} | ||
@@ -201,0 +239,0 @@ }; |
@@ -28,5 +28,7 @@ var fs = require('fs'); | ||
var socket; | ||
describe('koa-ws', function () { | ||
it ('should be able to attach middleware to app', function () { | ||
it('expect to be able to attach middleware to app', function () { | ||
var middleware = require('../src/middleware'); | ||
@@ -37,10 +39,10 @@ app.use(middleware(app)); | ||
it ('should be able to register a simple route', function () { | ||
it('expect to be able to register a simple server method', function () { | ||
app.ws.register('hello', function* () { | ||
this.result('world'); | ||
}); | ||
expect(app.ws.methods.hello).to.be.a('function'); | ||
expect(app.ws._methods.hello).to.be.a('function'); | ||
}); | ||
it ('should be able to register namespaced routes', function () { | ||
it('expect to be able to register namespaced server methods', function () { | ||
app.ws.register('user', { | ||
@@ -52,8 +54,8 @@ create: function* () { this.result('ok'); }, | ||
expect(app.ws.methods['user:create']).to.be.a('function'); | ||
expect(app.ws.methods['user:update']).to.be.a('function'); | ||
expect(app.ws.methods['user:update']).to.be.a('function'); | ||
expect(app.ws._methods['user:create']).to.be.a('function'); | ||
expect(app.ws._methods['user:update']).to.be.a('function'); | ||
expect(app.ws._methods['user:update']).to.be.a('function'); | ||
}); | ||
it ('should be able to listen to the same port as koa server', function (done) { | ||
it('expect server to be able to listen to the same port as koa server', function (done) { | ||
app.listen(3000, function () { | ||
@@ -63,8 +65,11 @@ expect(app.ws.server._server).to.be.a('object'); | ||
}); | ||
request(app.server) | ||
.get('/'); | ||
// Connect and generate session | ||
request(app.server).get('/'); | ||
}); | ||
it ('websocket client should be able to connect to server', function (done) { | ||
it('expect websocket client to be able to connect to server', function (done) { | ||
app.ws.server.on('connection', function (wss) { | ||
socket = wss; | ||
}); | ||
client = require('../src/client'); | ||
@@ -77,3 +82,3 @@ client.connect(); | ||
it ('should get world when hello method is called', function (done) { | ||
it('expect client to recieve result world when hello server method is called', function (done) { | ||
client.method('hello', function (err, payload) { | ||
@@ -86,5 +91,6 @@ expect(err).to.be.a('null'); | ||
it ('should be able to call namespaced events', function (done) { | ||
it('excpect client to be able to call namespaced server methods', function (done) { | ||
client.method('user:create', function (err, payload) { | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
}); | ||
@@ -94,2 +100,3 @@ | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
}); | ||
@@ -99,2 +106,3 @@ | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
done(); | ||
@@ -104,3 +112,33 @@ }); | ||
it ('should return error -32700 parse error', function (done) { | ||
it('expect to be able to register namespaced client methods', function () { | ||
client.register('user', { | ||
create: function () { this.result('ok'); }, | ||
update: function () { this.result('ok'); }, | ||
delete: function () { this.result('ok'); } | ||
}); | ||
expect(client._methods['user:create']).to.be.a('function'); | ||
expect(client._methods['user:update']).to.be.a('function'); | ||
expect(client._methods['user:update']).to.be.a('function'); | ||
}); | ||
it('expect server to be able to call namespaced client methods', function (done) { | ||
socket.method('user:create', function (err, payload) { | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
}); | ||
socket.method('user:update', function (err, payload) { | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
}); | ||
socket.method('user:delete', function (err, payload) { | ||
expect(err).to.be.a('null'); | ||
expect(payload).to.equal('ok'); | ||
done(); | ||
}); | ||
}); | ||
it('expect server to return error -32700 parse error', function (done) { | ||
client.once('message', function (payload) { | ||
@@ -114,3 +152,3 @@ var payload = JSON.parse(payload); | ||
it ('should return error -32600 invalid request', function (done) { | ||
it('expect server to return error -32600 invalid request', function (done) { | ||
client.once('message', function (payload) { | ||
@@ -124,3 +162,3 @@ var payload = JSON.parse(payload); | ||
it ('should return error -32602 invalid params', function (done) { | ||
it('expect server to return error -32602 invalid params', function (done) { | ||
client.method('hello', 'world!', function (err, payload) { | ||
@@ -132,3 +170,3 @@ expect(err.code).to.be.equal(-32602); | ||
it ('should return error -32601 method not found', function (done) { | ||
it('expect server to return error -32601 method not found', function (done) { | ||
client.method('foo', function (err, payload) { | ||
@@ -140,3 +178,3 @@ expect(err.code).to.be.equal(-32601); | ||
it ('should serve the client library at /koaws.js', function (done) { | ||
it('expect to be able to serve the client library at /koaws.js', function (done) { | ||
request(app.server) | ||
@@ -143,0 +181,0 @@ .get('/koaws.js') |
27923
620