Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/feathers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ var providers = require('./providers');
* @api public
*/

function createApplication() {
function createApplication(config) {
var app = express();
Proto.mixin(Application, app);
app.init();

// Add REST provider by default, can always be disabled using app.disable('feathers rest')
app.use(express.urlencoded()).use(express.json()).configure(providers.rest());
if(!config || config.rest) {
app.use(express.urlencoded()).use(express.json()).configure(providers.rest());
}

return app;
}

Expand Down
13 changes: 8 additions & 5 deletions lib/providers/rest/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
'use strict';

var _ = require('lodash');
var wrappers = require('./wrappers');

module.exports = function (config) {
config = config || {};

var responder = config.responder || function (req, res) {
res.format(_.extend({
var handler = config.handler || function (req, res) {
res.format({
'application/json': function () {
res.json(res.data);
}
}, config.formatters));
});
};

if(typeof config === 'function') {
handler = config;
}

return function () {
var app = this;

Expand Down Expand Up @@ -47,7 +50,7 @@ module.exports = function (config) {
// PATCH /:id -> service.patch(id, data, params, callback)
.patch(uri + '/:id', app.rest.patch(service));

app.use(uri, responder);
app.use(uri, handler);
});
};
};
26 changes: 26 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ app.use('/todos', {
});
```

The default REST handler is a middleware that formats the data retrieved by the service as JSON. REST handling will be set up automatically when calling `var app = feathers()`. If you would like to configure the REST provider yourself, call `var app = feathers({ rest: false });`.

Then you can configure it manually and add your own `handler` middleware that, for example just renders plain text with the todo description (`res.data` contains the data returned by the service):

```js
var app = feathers({ rest: false });

app.use(feathers.urlencoded()).use(feathers.json())
.configure(feathers.rest(function restFormatter(req, res) {
res.format({
'text/plain': function() {
res.end('The todo is: ' + res.data.description);
}
});
}))
.use('/todo', {
get: function (id, params, callback) {
callback(null, { description: 'You have to do ' + id });
}
});
```

__Note:__ When configuring REST this way, you *have* to add `app.use(feathers.urlencoded()).use(feathers.json())` to support request body parsing.

If you want to add other middleware *before* the REST handler, simply call `app.use(middleware)` before configuring the handler.

### 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. 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):
Expand Down
64 changes: 58 additions & 6 deletions test/providers/rest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,16 @@ describe('REST provider', function () {
});
});

it('throws a 405 for undefined service methods', function(done) {
it('throws a 405 for undefined service methods', function (done) {
var app = feathers().use('todo', {
get: function(id, params, callback) {
callback(null, { description: 'You have to do ' + id });
}
});
get: function (id, params, callback) {
callback(null, { description: 'You have to do ' + id });
}
});

/* jshint ignore:start */
// Error handler
app.use(function(error, req, res, next) {
app.use(function (error, req, res, next) {
assert.equal(error.message, 'Can not call service method .find');
res.json({ message: error.message });
});
Expand All @@ -168,4 +168,56 @@ describe('REST provider', function () {
});
});
});

it('disables REST and lets you set the handler manually', function(done) {
var app = feathers({ rest: false });

app.configure(feathers.rest(function restFormatter(req, res) {
res.format({
'text/plain': function() {
res.end('The todo is: ' + res.data.description);
}
});
}))
.use('/todo', {
get: function (id, params, callback) {
callback(null, { description: 'You have to do ' + id });
}
});

var server = app.listen(4776);
request('http://localhost:4776/todo/dishes', function (error, response, body) {
assert.equal(body, 'The todo is: You have to do dishes');
server.close(done);
});
});

it('Lets you configure your own middleware before the handler (#40)', function(done) {
var data = { description: 'Do dishes!', id: 'dishes' };
var app = feathers({ rest: false });

app.use(function defaultContentTypeMiddleware (req, res, next) {
req.headers['content-type'] = req.headers['content-type'] || 'application/json';
next();
})
.use(feathers.urlencoded())
.use(feathers.json())
.configure(feathers.rest())
.use('/todo', {
create: function (data, params, callback) {
callback(null, data);
}
});

var server = app.listen(4775);
request({
method: 'POST',
url: 'http://localhost:4775/todo',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
}, function (error, response, body) {
assert.deepEqual(JSON.parse(body), data);
server.close(done);
});
});
});