diff --git a/.jshintrc b/.jshintrc index 3dbb032182..8b243dadc4 100644 --- a/.jshintrc +++ b/.jshintrc @@ -6,5 +6,7 @@ "after": true, "exports": true }, + "unused": true, + "undef": true, "node": true } \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000000..62c893550a --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 2ca91f2895..43be7c3197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js node_js: - "0.10" - - "0.8" \ No newline at end of file + - "0.8" + # - "0.11" \ No newline at end of file diff --git a/documentation.md b/documentation.md index 1468708c88..c3b728ca43 100644 --- a/documentation.md +++ b/documentation.md @@ -1,17 +1,57 @@ ## Introduction -Feathers sits right on top of Express, one of the most popular web frameworks for NodeJS. If you are not familiar with Express head over to the [Express Guides](http://expressjs.com/guide.html). Feathers works the exact same way except that `var app = require('express')();` is replaced with `var app = require('feathers')()`. The small differences and additional functionality available is outline in the following documentation. +Feathers sits right on top of Express, one of the most popular web frameworks for [NodeJS](http://nodejs.org/). If you are not familiar with Express head over to the [Express Guides](http://expressjs.com/guide.html) to get an idea. Feathers works the exact same way except that `var app = require('express')();` is replaced with `var app = require('feathers')()`. The small differences and additional functionality available is outline in the following documentation. ## Configuration ### REST -Exposing services through a RESTful JSON interface is enabled by default. If you only want to use SocketIO -call `app.disabled('feathers rest')` _before_ registering any services. +Exposing services through a RESTful JSON interface is enabled by default. If you only want to use SocketIO call `app.disabled('feathers rest')` _before_ registering any services. + +To set service parameters in a middleware, just attach it to the `req.feathers` object which will become the params for any resulting service call: + +```js +app.use(function(req, res) { + req.feathers.data = 'Hello world'; +}); + +app.use('/todos', { + get: function(name, params, callback) { + console.log(params.data); // -> 'Hello world' + callback(null, { + id: name, + params: params, + description: "You have to do " + name + "!" + }); + } +}); +``` ### SocketIO -To expose services via [SocketIO](http://socket.io/) call `app.configure(feathers.socketio())`. It is also possible pass a `function(io) {}` when initializing the provider where `io` is the main SocketIO object so you can listen to custom events, change the configuration or add [authorization](https://github.com/LearnBoost/socket.io/wiki/Authorizing): +To expose services via [SocketIO](http://socket.io/) call `app.configure(feathers.socketio())`. It is also possible pass a `function(io) {}` when initializing the provider where `io` is the main SocketIO object. Since Feathers is only using the SocketIO default configuration, this is a good spot to initialize the [recommended production settings](https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO#recommended-production-settings): + +```js +app.configure(feathers.socketio(function(io) { + io.enable('browser client minification'); // send minified client + io.enable('browser client etag'); // apply etag caching logic based on version number + io.enable('browser client gzip'); // gzip the file + io.set('log level', 1); // reduce logging + + // enable all transports (optional if you want flashsocket support, please note that some hosting + // providers do not allow you to create servers that listen on a port different than 80 or their + // default port) + io.set('transports', [ + 'websocket' + , 'flashsocket' + , 'htmlfile' + , 'xhr-polling' + , 'jsonp-polling' + ]); +})); +``` + +This is also the place to listen to custom events or add [authorization](https://github.com/LearnBoost/socket.io/wiki/Authorizing): ```js app.configure(feathers.socketio(function(io) { @@ -23,6 +63,7 @@ app.configure(feathers.socketio(function(io) { }); io.set('authorization', function (handshakeData, callback) { + // Authorize using the /users service app.lookup('users').find({ username: handshakeData.username, password: handshakeData.password @@ -33,28 +74,95 @@ app.configure(feathers.socketio(function(io) { Once the server has been started with `app.listen()` the SocketIO object is available as `app.io`. +### Primus + +[Primus](https://github.com/primus/primus) is a universal wrapper for real-time frameworks and allows you to transparently use Engine.IO, WebSockets, BrowserChannel, SockJS and Socket.IO. Set it up with `feathers.primus(configuration [, fn])` where `configuration` is the [Primus server configuration](https://github.com/primus/primus#getting-started) and `fn` an optional callback with the Primus server instance that can e.g. be used for setting up [authorization](https://github.com/primus/primus#authorization): + +```js +// Set up Primus with SockJS +app.configure(feathers.primus({ + transformer: 'sockjs' +}, function(primus) { + // Set up Primus authorization here + primus.authorize(function (req, done) { + var auth; + + try { auth = authParser(req.headers['authorization']) } + catch (ex) { return done(ex) } + + // Do some async auth check + authCheck(auth, done); + }); +})); +``` + +In the Browser you can connect like this: + +```html + + +``` + ## API ### listen -`app.listen([port])` starts the application on the given port. Before calling the original [Express app.listen([port])](http://expressjs.com/api.html#app.listen) Feathers will initialize the SocketIO server (if set up) and call all services `setup(app, path)` methods in the order they have been registered. +`app.listen([port])` starts the application on the given port. It will first call the original [Express app.listen([port])](http://expressjs.com/api.html#app.listen), then run `app.setup(server)` (see below) with the server object and then return the server object. + +### setup + +`app.setup(server)` is used initialize all services by calling each services `.setup(app, path)` method (if available). +It will also use the `server` instance passed (e.g. through `http.createServer`) to set up SocketIO (if enabled) and any other provider that might require the server instance. + +Normally `app.setup` will be called automatically when starting the application via `app.listen([port])` but there are cases when you need to initialize the server separately: + +__HTTPS__ + +With your Feathers application initialized it is easy to set up an HTTPS REST and SocketIO server: ```js -var app = feathers(); -app.use('/todos', { - setup: function(app, path) { - // path -> 'todos' - } -}); +app.configure(feathers.socketio()).use('/todos', todoService); + +var https = require('https'); +var server = https.createServer({ + key: fs.readFileSync('privatekey.pem'), + cert: fs.readFileSync('certificate.pem') +}, app).listen(443); + +// Call app.setup to initialize all services and SocketIO +app.setup(server); +``` + +__Virtual Hosts__ + +You can use `feathers.vhost` (which is the same as [Express and Connect .vhost](http://www.senchalabs.org/connect/vhost.html)) to run your Feathers app on a virtual host: + +```js +app.use('/todos', todoService); -var server = app.listen(8080); +var host = feathers().use(feathers.vhost('foo.com', app)); +var server = host.listen(8080); -server.close(); +// Here we need to call app.setup because .listen on our virtal hosted +// app is never called +app.setup(server); ``` ### lookup -`app.lookup(path)` returns the wrapped service object for the given path. Note that the returned object will provide the same methods and functionality as the original service but actually is a new object with additional functionality added (most notably it is possible to listen to service events). `path` can be the service name with or without leading and trailing slashes. +`app.lookup(path)` returns the wrapped service object for the given path. Note that Feathers internally creates a new object from each registered service. This means that the object returned by `lookup` will provide the same methods and functionality as the original service but also functionality added by Feathers (most notably it is possible to listen to service events). `path` can be the service name with or without leading and trailing slashes. ```js app.use('/my/todos', { @@ -97,9 +205,13 @@ app.use('/todos', { }); ``` +### service + +`app.service([path], service)` is what is called internally by `app.use([path], service)` if a service object is being passed. Use it instead of `app.use([path], service)` if you want to be more explicit that you are registering a service. `app.service` does __not__ provide the Express `app.use` functionality and doesn't check the service object for valid methods. + ## Services -A service can be any JavaScript object that offers one or more of the `find`, `get`, `create`, `update`, `remove` and `setup` service methods: +A service can be any JavaScript object that offers one or more of the `find`, `get`, `create`, `update`, `remove` and `setup` service methods with the following signatures: ```js var myService = { @@ -112,7 +224,7 @@ var myService = { } ``` -All callbacks follow the `function(error, data)` NodeJS convention. `params` can contain any additional parameters, for example the currently authenticated user. REST service calls set `params.query` with the query parameters (e.g. a query string like `?status=active&type=user` becomes `{ status: "active", type: "user" }`). +All callbacks follow the `function(error, data)` NodeJS convention. `params` can contain any additional parameters, for example the currently authenticated user. REST service calls set `params.query` with the query parameters (e.g. a query string like `?status=active&type=user` becomes `{ query: { status: "active", type: "user" } }`). ### find @@ -167,7 +279,7 @@ __SocketIO__ ```js socket.emit('todo::create', { description: 'I really have to iron' -}, function(error, data) { +}, {}, function(error, data) { }); ``` @@ -227,7 +339,7 @@ var myService = { get: function(name, params, callback) { this.todo.get('take out trash', {}, function(error, todo) { - callback(null, { + callback(error, { name: name, todo: todo }); @@ -266,7 +378,7 @@ var myService = { ## Events -Any registered service will be automatically turned into an event emitter that emits events when a resource has changed, that is a `create`, `update` or `remove` service call returned successfully. It is therefore possible to bind to the below events via `app.lookup(servicename).on()` and, if enabled, all events will also broadcast to all connected SocketIO clients in the form of ` `. +Any registered service will be automatically turned into an event emitter that emits events when a resource has changed, that is a `create`, `update` or `remove` service call returned successfully. It is therefore possible to bind to the below events via `app.lookup(servicename).on()` and, if enabled, all events will also broadcast to all connected SocketIO clients in the form of ` `. Note that the service path will always be stripped of leading and trailing slashes regardless of how it has been registered (e.g. `/my/service/` will become `my/service`). ### created @@ -310,16 +422,12 @@ __SocketIO__ The `updated` event will be published with the callback data when a service `update` calls back successfully. ```js -app.use('/todos', { +app.use('/my/todos/', { update: function(id, data, params, callback) { callback(null, data); } }); -app.lookup('/todos').on('updated', function(todo) { - console.log('Updated todo', todo); -}); - app.listen(8000); ``` @@ -330,15 +438,15 @@ __SocketIO__ ``` @@ -376,14 +484,22 @@ __SocketIO__ ## Why? -We know... Oh God another NodeJS framework! Yes we are also very tired of seeing all these NodeJS frameworks. All the rails clones are getting a bit boring and really aren't taking advantage of the real strengths of NodeJS. We wanted to take a different approach than every other framework we have seen, because we believe that data is core to the web and should be the core focus of web applications. +We know... Oh God another NodeJS framework! We really didn't want to add another name to the long list of NodeJS web frameworks but also wanted to explore a different approach than any other framework we have seen. We strongly believe that data is the core of the web and should be the focus of web applications. -We also think that your data resources can and should be encapsulated in such a way that they can be ultra scalable and self contained. The MVC pattern works well but it is becoming antiquated in today's web. Frankly you don't need it and they tend to become bloated. +We also think that your data resources can and should be encapsulated in such a way that they can be scalable, easily testable and self contained. The classic web MVC pattern used to work well but is becoming antiquated in today's web. With that being said there are some amazing frameworks already out there and we wanted to leverage the ideas that have been put into them, which is why Feathers is built on top of [Express](http://expressjs.com) and is inspired in part by [Sails](http://sailsjs.org), [Flatiron](http://flatironjs.org) and [Derby](http://derbyjs.com). ## Changelog +__0.3.0__ + +- Added [Primus](https://github.com/primus/primus) provider ([#34](https://github.com/feathersjs/feathers/pull/34)) +- `app.setup(server)` to support HTTPS (and other functionality that requires a custom server) ([#33](https://github.com/feathersjs/feathers/pull/33)) +- Removed bad SocketIO configuration ([#19](https://github.com/feathersjs/feathers/issues/19)) +- Add .npmignore to not publish .idea folder ([#30](https://github.com/feathersjs/feathers/issues/30)) +- Remove middleware: connect.bodyParser() ([#27](https://github.com/feathersjs/feathers/pull/27)) + __0.2.0__ - Pre-initialize `req.feathers` in REST provider to set service parameters diff --git a/lib/application.js b/lib/application.js index 60fa92faa5..5b87c54c21 100644 --- a/lib/application.js +++ b/lib/application.js @@ -18,6 +18,26 @@ module.exports = { }); }, + service: function(location, service) { + var protoService = Proto.extend(service); + var self = this; + + location = stripSlashes(location); + + // Add all the mixins + _.each(this.mixins, function (fn) { + fn.call(self, protoService); + }); + + // Run the provider functions to register the service + _.each(this.providers, function (provider) { + provider(location, protoService); + }); + + this.services[location] = protoService; + return this; + }, + use: function (location, service) { var hasServiceMethod = function (name) { return typeof service !== 'undefined' && typeof service[name] === 'function'; @@ -25,23 +45,7 @@ module.exports = { // Check for service (any object with at least one service method) if (_.some(this.methods, hasServiceMethod)) { - var protoService = Proto.extend(service); - var self = this; - - location = stripSlashes(location); - - // Add all the mixins - _.each(this.mixins, function (fn) { - fn.call(self, protoService); - }); - - // Run the provider functions to register the service - _.each(this.providers, function (provider) { - provider(location, protoService); - }); - - this.services[location] = protoService; - return this; + return this.service(location, service); } // Pass to the original express app @@ -52,15 +56,20 @@ module.exports = { return this.services[stripSlashes(location)]; }, - listen: function () { - var self = this; + setup: function() { // Setup each service (pass the app so that they can look up other services etc.) - _.each(self.services, function (service, path) { + _.each(this.services, function (service, path) { if (typeof service.setup === 'function') { - service.setup(self, path); + service.setup(this, path); } - }); + }.bind(this)); - return this._super.apply(this, arguments); + return this; + }, + + listen: function () { + var server = this._super.apply(this, arguments); + this.setup(server); + return server; } }; diff --git a/lib/feathers.js b/lib/feathers.js index da03addfcd..c3d8bbef35 100644 --- a/lib/feathers.js +++ b/lib/feathers.js @@ -18,7 +18,7 @@ function createApplication() { Proto.mixin(Application, app); app.init(); // Add REST provider by default, can always be disabled using app.disable('feathers rest') - app.use(express.bodyParser()).configure(providers.rest()); + app.use(express.urlencoded()).use(express.json()).configure(providers.rest()); return app; } diff --git a/lib/mixins/event.js b/lib/mixins/event.js index 1714159eef..eb1a066ddd 100644 --- a/lib/mixins/event.js +++ b/lib/mixins/event.js @@ -1,6 +1,5 @@ 'use strict'; -var Proto = require('uberproto'); var _ = require('underscore'); var rubberduck = require('rubberduck'); var EventEmitter = require('events').EventEmitter; diff --git a/lib/providers/index.js b/lib/providers/index.js index 278897d473..8b8e267ac7 100644 --- a/lib/providers/index.js +++ b/lib/providers/index.js @@ -2,5 +2,6 @@ module.exports = { rest: require('./rest'), - socketio: require('./socketio') + socketio: require('./socketio'), + primus: require('./primus') }; diff --git a/lib/providers/primus.js b/lib/providers/primus.js new file mode 100644 index 0000000000..1db4ade9e6 --- /dev/null +++ b/lib/providers/primus.js @@ -0,0 +1,64 @@ +'use strict'; + +var _ = require('underscore'); +var Proto = require('uberproto'); +var Primus = require('primus'); +var Emitter = require('primus-emitter'); + +module.exports = function(config, configurer) { + return function() { + var app = this; + var services = {}; + + app.enable('feathers primus'); + + // Monkey patch app.setup(server) + Proto.mixin({ + setup: function(server) { + var self = this; + var result = this._super.apply(this, arguments); + + if (this.disabled('feathers primus')) { + return result; + } + + var primus = this.primus = new Primus(server, config); + primus.use('emitter', Emitter); + + _.each(services, function(service, path) { + // If the service emits events that we want to listen to (Event mixin) + if (typeof service.on === 'function' && service._serviceEvents) { + _.each(service._serviceEvents, function(ev) { + service.on(ev, function(data) { + primus.forEach(function (spark) { + spark.send(path + ' ' + ev, data); + }); + }); + }); + } + }); + + primus.on('connection', function(spark) { + _.each(services, function(service, path) { + _.each(self.methods, function(method) { + var name = path + '::' + method; + if (service[method]) { + spark.on(name, service[method].bind(service)); + } + }); + }); + }); + + if (typeof configurer === 'function') { + configurer.call(this, primus); + } + + return result; + } + }, app); + + app.providers.push(function(path, service) { + services[path] = service; + }); + }; +}; diff --git a/lib/providers/socketio.js b/lib/providers/socketio.js index d02e226ee7..1b58258dca 100644 --- a/lib/providers/socketio.js +++ b/lib/providers/socketio.js @@ -2,66 +2,58 @@ var _ = require('underscore'); var socketio = require('socket.io'); -var listen = function (httpServer) { - var io = socketio.listen(httpServer); +var Proto = require('uberproto'); - io.enable('browser client etag'); - io.set('log level', 0); - - io.set('transports', [ - 'xhr-polling', 'websocket', 'flashsocket', - 'htmlfile', 'jsonp-polling' - ]); - - return io; -}; - -module.exports = function (config) { - return function () { +module.exports = function(config) { + return function() { var app = this; - var oldListen = app.listen; var services = {}; app.enable('feathers socketio'); - // Overwrite Expresss `listen` - app.listen = function () { - var httpServer = oldListen.apply(this, arguments); - if (app.disabled('feathers socketio')) { - return httpServer; - } - var io = this.io = listen(httpServer); + // Monkey patch app.setup(server) + Proto.mixin({ + setup: function(server) { + var self = this; + var result = this._super.apply(this, arguments); - _.each(services, function (service, path) { - // If the service emits events that we want to listen to (Event mixin) - if (typeof service.on === 'function' && service._serviceEvents) { - _.each(service._serviceEvents, function (ev) { - service.on(ev, function (data) { - io.sockets.emit(path + ' ' + ev, data); - }); - }); + if (this.disabled('feathers socketio')) { + return result; } - }); - io.sockets.on('connection', function (socket) { - _.each(services, function (service, path) { - _.each(app.methods, function (method) { - var name = path + '::' + method; - if (service[method]) { - socket.on(name, _.bind(service[method], service)); - } + var io = this.io = socketio.listen(server); + + _.each(services, function(service, path) { + // If the service emits events that we want to listen to (Event mixin) + if (typeof service.on === 'function' && service._serviceEvents) { + _.each(service._serviceEvents, function(ev) { + service.on(ev, function(data) { + io.sockets.emit(path + ' ' + ev, data); + }); + }); + } + }); + + io.sockets.on('connection', function(socket) { + _.each(services, function(service, path) { + _.each(self.methods, function(method) { + var name = path + '::' + method; + if (service[method]) { + socket.on(name, service[method].bind(service)); + } + }); }); }); - }); - if(typeof config === 'function') { - config.call(this, io); - } + if (typeof config === 'function') { + config.call(this, io); + } - return httpServer; - }; + return result; + } + }, app); - app.providers.push(function (path, service) { + app.providers.push(function(path, service) { services[path] = service; }); }; diff --git a/package.json b/package.json index fac14292a8..fa0a0c5132 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers", "description": "An ultra scalable, feather weight, data oriented framework", - "version": "0.2.0", + "version": "0.3.0", "homepage": "http://feathersjs.com", "repository": { "type": "git", @@ -36,9 +36,11 @@ "dependencies": { "uberproto": "~ 1.1.0", "express": "~ 3.4.0", - "rubberduck": "~0.2.0", + "rubberduck": "~1.x", "underscore": "~1.5.0", - "socket.io": "~0.9.0" + "socket.io": "~0.9.0", + "primus-emitter": "~2.0.5", + "primus": "~1.5.1" }, "devDependencies": { "request": "~2.21.0", diff --git a/test/application.test.js b/test/application.test.js index f31c961903..3fc9c1ae48 100644 --- a/test/application.test.js +++ b/test/application.test.js @@ -4,14 +4,15 @@ var assert = require('assert'); var Proto = require('uberproto'); var io = require('socket.io-client'); var request = require('request'); +var https = require('https'); +var fs = require('fs'); var feathers = require('../lib/feathers'); -var express = require('express'); describe('Feathers application', function () { it('registers service and looks it up with and without leading and trailing slashes', function () { var dummyService = { - find: function (params, callback) { + find: function () { // No need to implement this } }; @@ -63,7 +64,9 @@ describe('Feathers application', function () { var oldlog = console.log; console.log = function () {}; - var app = feathers().configure(feathers.socketio()).use('/todo', todoService); + var app = feathers().configure(feathers.socketio(function(io) { + io.set('log level', 0); + })).use('/todo', todoService); var server = app.listen(6999).on('listening', function () { console.log = oldlog; @@ -83,4 +86,57 @@ describe('Feathers application', function () { }); }); }); + + it('REST and SocketIO with SSL server (#25)', function(done) { + // For more info on Reqest HTTPS settings see https://github.com/mikeal/request/issues/418 + // This needs to be set so that the SocektIO client can connect + process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + + var todoService = { + get: function (name, params, callback) { + callback(null, { + id: name, + description: "You have to do " + name + "!" + }); + } + }; + + var oldlog = console.log; + console.log = function () {}; + var app = feathers().configure(feathers.socketio(function(io) { + io.set('log level', 0); + })).use('/secureTodos', todoService); + + var httpsServer = https.createServer({ + key: fs.readFileSync(__dirname + '/resources/privatekey.pem'), + cert: fs.readFileSync(__dirname + '/resources/certificate.pem'), + rejectUnauthorized: false, + requestCert: false + }, app).listen(7889); + + app.setup(httpsServer); + + httpsServer.on('listening', function() { + var socket = io.connect('https://localhost:7889', { secure: true, port: 7889 }); + + console.log = oldlog; + + request({ + url: 'https://localhost:7889/secureTodos/dishes', + strictSSL: false, + rejectUnhauthorized : false + }, function (error, response, body) { + assert.ok(response.statusCode === 200, 'Got OK status code'); + var data = JSON.parse(body); + assert.equal(data.description, 'You have to do dishes!'); + + socket.emit('secureTodos::get', 'laundry', {}, function (error, data) { + assert.equal(data.description, 'You have to do laundry!'); + + socket.disconnect(); + httpsServer.close(done); + }); + }); + }); + }); }); diff --git a/test/providers/primus.test.js b/test/providers/primus.test.js new file mode 100644 index 0000000000..457656e979 --- /dev/null +++ b/test/providers/primus.test.js @@ -0,0 +1,113 @@ +'use strict'; + +var feathers = require('../../lib/feathers'); +var fixture = require('./service-fixture'); +var todoService = fixture.Service; +var verify = fixture.verify; + +describe('Primus provider', function () { + var server, socket; + + before(function () { + server = feathers() + .configure(feathers.primus({ + transformer: 'socket.io' + }, function(primus) { + socket = new primus.Socket('http://localhost:7888'); + })) + .use('todo', todoService) + .listen(7888); + }); + + after(function (done) { + socket.socket.disconnect(); + server.close(done); + }); + + describe('CRUD', function () { + it('::find', function (done) { + socket.send('todo::find', {}, function (error, data) { + verify.find(data); + + done(error); + }); + }); + + it('::get', function (done) { + socket.send('todo::get', 'laundry', {}, function (error, data) { + verify.get('laundry', data); + + done(error); + }); + }); + + it('::create', function (done) { + var original = { + name: 'creating' + }; + + socket.send('todo::create', original, {}, function (error, data) { + verify.create(original, data); + + done(error); + }); + }); + + it('::update', function (done) { + var original = { + name: 'updating' + }; + + socket.send('todo::update', 23, original, {}, function (error, data) { + verify.update(23, original, data); + + done(error); + }); + }); + + it('::remove', function (done) { + socket.send('todo::remove', 11, {}, function (error, data) { + verify.remove(11, data); + + done(error); + }); + }); + }); + + describe('Events', function () { + it('created', function (done) { + var original = { + name: 'created event' + }; + + socket.on('todo created', function (data) { + verify.create(original, data); + done(); + }); + + socket.send('todo::create', original, {}, function () {}); + }); + + it('updated', function (done) { + var original = { + name: 'updated event' + }; + + socket.on('todo updated', function (data) { + verify.update(10, original, data); + done(); + }); + + socket.send('todo::update', 10, original, {}, function () {}); + }); + + it('removed', function (done) { + socket.on('todo removed', function (data) { + verify.remove(333, data); + done(); + }); + + socket.send('todo::remove', 333, {}, function () {}); + }); + }); +}); diff --git a/test/providers/socketio.test.js b/test/providers/socketio.test.js index daa59b77b4..c1c708f287 100644 --- a/test/providers/socketio.test.js +++ b/test/providers/socketio.test.js @@ -1,9 +1,7 @@ 'use strict'; -var assert = require('assert'); var feathers = require('../../lib/feathers'); var io = require('socket.io-client'); -var request = require('request'); var fixture = require('./service-fixture'); var todoService = fixture.Service; @@ -19,7 +17,9 @@ describe('SocketIO provider', function () { console.log = function () {}; server = feathers() - .configure(feathers.socketio()) + .configure(feathers.socketio(function(io) { + io.set('log level', 0); + })) .use('todo', todoService) .listen(7886); diff --git a/test/resources/certificate.pem b/test/resources/certificate.pem new file mode 100644 index 0000000000..6735645071 --- /dev/null +++ b/test/resources/certificate.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAgQCCQDugFqITnU/sDANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMC +Q0ExEDAOBgNVBAgTB0FsYmVydGExEDAOBgNVBAcTB0NhbGdhcnkxETAPBgNVBAoT +CEZlYXRoZXJzMREwDwYDVQQLEwhGZWF0aGVyczETMBEGA1UEAxMKRmVhdGhlcnNK +UzEjMCEGCSqGSIb3DQEJARYUaGVsbG9AZmVhdGhlcnNqcy5jb20wHhcNMTQwMTA0 +MDIwNTUyWhcNMTQwMjAzMDIwNTUyWjCBkTELMAkGA1UEBhMCQ0ExEDAOBgNVBAgT +B0FsYmVydGExEDAOBgNVBAcTB0NhbGdhcnkxETAPBgNVBAoTCEZlYXRoZXJzMREw +DwYDVQQLEwhGZWF0aGVyczETMBEGA1UEAxMKRmVhdGhlcnNKUzEjMCEGCSqGSIb3 +DQEJARYUaGVsbG9AZmVhdGhlcnNqcy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBALixfLwrvDDYAaaU62oycz8zwUpxCguyyXyhVDN/KMmP/I+HfkbcIrqj +tW0jbpRWiLhn5cw4K/cUTkfMj4AwaN5t2zq0FVFJdIddLxzuamyJLJFZfs5sPYWt +X6morPcu9RM7jwb3R1V852XjVWUj8neUAu7eUzKoSQ575kHsnKrdAgMBAAEwDQYJ +KoZIhvcNAQEFBQADgYEATVlxNPkSgkqBF4foUYNGnkvaiwhd88Mh/Ya3T3EnknF9 +Gz6KrlwWDDI8MkPmqabT2Ijg3LSec7WV+C8SETVFbWLOGV6N1ZVfodFzJ7EKMz5e +VvEIKnHfHpYOEa21E5u02+OfKahtW37eTEVmvcV67vYmW4HNa5QSZ5qfrrqcUhc= +-----END CERTIFICATE----- diff --git a/test/resources/certrequest.csr b/test/resources/certrequest.csr new file mode 100644 index 0000000000..41f83b2757 --- /dev/null +++ b/test/resources/certrequest.csr @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIB0jCCATsCAQAwgZExCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdBbGJlcnRhMRAw +DgYDVQQHEwdDYWxnYXJ5MREwDwYDVQQKEwhGZWF0aGVyczERMA8GA1UECxMIRmVh +dGhlcnMxEzARBgNVBAMTCkZlYXRoZXJzSlMxIzAhBgkqhkiG9w0BCQEWFGhlbGxv +QGZlYXRoZXJzanMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4sXy8 +K7ww2AGmlOtqMnM/M8FKcQoLssl8oVQzfyjJj/yPh35G3CK6o7VtI26UVoi4Z+XM +OCv3FE5HzI+AMGjebds6tBVRSXSHXS8c7mpsiSyRWX7ObD2FrV+pqKz3LvUTO48G +90dVfOdl41VlI/J3lALu3lMyqEkOe+ZB7Jyq3QIDAQABoAAwDQYJKoZIhvcNAQEF +BQADgYEAFN1xm2Jc5EwDsiJwjUQkVCYLfAPz8FxLx8XCY7JugPCZWxeJ3w9C3Ymz +hET//7uxNg6q7EO9CI33vP5eOdI8oC8XQffh4GzCoSrmGrKpHSqVh3zN/rCoB4BY +f4nJofTka5iENjMdA0R8//Wp7F1u7xhriuxaRiZoFEPaCIsrvK4= +-----END CERTIFICATE REQUEST----- diff --git a/test/resources/privatekey.pem b/test/resources/privatekey.pem new file mode 100644 index 0000000000..3a39a23926 --- /dev/null +++ b/test/resources/privatekey.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC4sXy8K7ww2AGmlOtqMnM/M8FKcQoLssl8oVQzfyjJj/yPh35G +3CK6o7VtI26UVoi4Z+XMOCv3FE5HzI+AMGjebds6tBVRSXSHXS8c7mpsiSyRWX7O +bD2FrV+pqKz3LvUTO48G90dVfOdl41VlI/J3lALu3lMyqEkOe+ZB7Jyq3QIDAQAB +AoGAYCTkzf/mY3bOxSzYr9u7ardCc8IMfLKBeMNy1avoS6UM0Jqz/acy3P3DwCCl +u8qgOX68fWbwXBrR9UZjnVOWAvAgACS9bSTR4UxXuHve9YHf1s1Idm1Ck8CopiuY +0PTiuF7OJp6U7fc1RjO5F5tvSMuYbh+68Vpx9SQRfDHYqnECQQD1KnhSRDjLCfoB +lLfTew99W51OTx2NPRKRXwZH/YwlgRl/cAgJhdemah/AAavB6BUdqEXdiIviEHuT +UsfAXhf7AkEAwNrmEI3B4gtMRKJAsyWAKGFxDHuC9wGkhSxCVihQuxXtqEMX7Qnx +ucU9bRRtUgVPcOmFEtpPsI4e0wkTMg+ZBwJAPL+ERuYuqGjVcPTXw+g3Q1mjFddW +vDuI0UqZdNcnlddyaPhqlWl7sPmU2m/PjmGicdHTVfxSpPZumGenpUvrZwJAdodS +9QObEOmus1Qhfbljne3dhDV5FYTd77d3Aer/Syy8BzlNQDNnbKysBxmR4uI+o//x ++NdSOQnwKfYe5RqvCwJBAMfq911uzlD8Kd9s0n+MJe8b5/duYOtgPZvaIFWOWyNm +0aJE/VovVhk2JGvIU9kxdgt9O4N0x2XukS2hq7I1Xts= +-----END RSA PRIVATE KEY-----