diff --git a/lib/providers/socketio.js b/lib/providers/socketio.js index 74e2368bbd..d0f798d3d8 100644 --- a/lib/providers/socketio.js +++ b/lib/providers/socketio.js @@ -4,6 +4,14 @@ var _ = require('lodash'); var socketio = require('socket.io'); var Proto = require('uberproto'); +// The position of the params parameters for a service method so that we can extend them +// default is 1 +var paramsPositions = { + find: 0, + update: 2, + patch: 2 +}; + module.exports = function(config) { return function() { var app = this; @@ -38,8 +46,14 @@ module.exports = function(config) { _.each(services, function(service, path) { _.each(self.methods, function(method) { var name = path + '::' + method; - if (service[method]) { - socket.on(name, service[method].bind(service)); + var position = typeof paramsPositions[method] !== 'undefined' ? paramsPositions[method] : 1; + + if (typeof service[method] === 'function') { + socket.on(name, function() { + var args = _.toArray(arguments); + args[position] = _.extend({}, args[position], socket.handshake.feathers); + service[method].apply(service, args); + }); } }); }); diff --git a/readme.md b/readme.md index bbe0840153..567f7b4349 100644 --- a/readme.md +++ b/readme.md @@ -74,6 +74,24 @@ app.configure(feathers.socketio(function(io) { })); ``` +Similar than the REST middleware, the SocketIO handshakes `feathers` property will be extended +for service parameters: + +```js +app.configure(feathers.socketio(function(io) { + io.set('authorization', function (handshake, callback) { + handshake.feathers.user = { name: 'David' }; + }); +})); + +app.use('todos', { + create: function(data, params, callback) { + // When called via SocketIO: + params.user // -> { name: 'David' } + } +}); +``` + Once the server has been started with `app.listen()` the SocketIO object is available as `app.io`. ### Primus diff --git a/test/providers/socketio.test.js b/test/providers/socketio.test.js index 3623b9efa2..4d2fd42e62 100644 --- a/test/providers/socketio.test.js +++ b/test/providers/socketio.test.js @@ -1,14 +1,20 @@ 'use strict'; +var _ = require('lodash'); var feathers = require('../../lib/feathers'); var io = require('socket.io-client'); +var assert = require('assert'); var fixture = require('./service-fixture'); var todoService = fixture.Service; var verify = fixture.verify; describe('SocketIO provider', function () { - var server, socket; + var server, socket, app, + socketParams = { + user: { name: 'David' }, + provider: 'socketio' + }; before(function () { // This seems to be the only way to not get the @@ -16,12 +22,17 @@ describe('SocketIO provider', function () { var oldlog = console.log; console.log = function () {}; - server = feathers() + app = feathers() .configure(feathers.socketio(function(io) { io.set('log level', 0); + io.set('authorization', function (handshake, callback) { + handshake.feathers = socketParams; + callback(null, true); + }); })) - .use('todo', todoService) - .listen(7886); + .use('todo', todoService); + + server = app.listen(7886); console.log = oldlog; @@ -33,6 +44,47 @@ describe('SocketIO provider', function () { server.close(done); }); + it('passes handshake as service parameters', function(done) { + var service = app.lookup('todo'); + var old = { + find: service.find, + create: service.create, + update: service.update, + remove: service.remove + }; + + service.find = function(params) { + assert.deepEqual(params, socketParams, 'Handshake parameters passed on proper position'); + old.find.apply(this, arguments); + }; + + service.create = function(data, params) { + assert.deepEqual(params, socketParams, 'Passed handshake parameters'); + old.create.apply(this, arguments); + }; + + service.update = function(id, data, params) { + assert.deepEqual(params, _.extend(socketParams, { + test: 'param' + }), 'Extended handshake paramters with original'); + old.update.apply(this, arguments); + }; + + service.remove = function(id, params) { + assert.equal(params.provider, 'socketio', 'Handshake parameters have priority'); + old.remove.apply(this, arguments); + }; + + socket.emit('todo::create', {}, {}, function () { + socket.emit('todo::update', 1, {}, { test: 'param' }, function() { + socket.emit('todo::remove', 1, { provider: 'something' }, function() { + _.extend(service, old); + done(); + }); + }); + }); + }); + describe('CRUD', function () { it('::find', function (done) { socket.emit('todo::find', {}, function (error, data) {