Hi,
How can I add custom method to service like "count" method? or as loopback does ( http://docs.strongloop.com/display/DOC/Exposing+models+over+a+REST+API ).
Thanks
Having a method like that is not very RESTful (I'd probably try to use the HTTP range header) but it is still easy to add as a custom middleware in the services .setup:
var MyService = {
items: [],
find: function(params, callback) {
callback(null, this.items)
},
count: function(callback) {
callback(null, {
total: this.items.length
});
},
// ...
setup: function(app, path) {
var self = this;
app.get(path + '/count', function(req, res) {
self.count(function(error, data) {
res.end(data);
});
});
}
}
Another option would be for .find to return an object instead of an array that contains counting information and add a params flag that allows you to only retrieve that:
var MyService = {
items: [],
find: function(params, callback) {
var info = {
from: 0,
to: items.length,
total: items.length
};
if(!params.query.count) {
info.data = this.items;
}
callback(null, info);
}
}
Thanks a lot.
Simply use the app.get(path + '/count', function(req, res) doesn't seem to work, it'll still route to the service get method, also if you add additional path under the service path, it won't work either.
The following code doesn't work for me
app.route('/user/auth/signin').post(usersCtrl.signin);
app.route('/user/signin').post(usersCtrl.signin);
it get to work when I change the path to:
app.route('/auth/signin').post(usersCtrl.signin);
Can anyone answer what is behind the scenes?
Odd, I think this used to work before switching to Express 4 (v0.4.x). Internally it just sets up a router for the service at https://github.com/feathersjs/feathers/blob/master/lib/providers/rest/index.js#L40. It seems like when setting up a router like that you can't add any other routes. I don't think for services it makes a difference if we are using a router or individual routes so we should probably change it back to individual routes so that this is still possible.
@daffl What was the issue here? I didn't quite follow. It's not routing quite properly when you define a resource?
Maybe app.route isn't quite the right thing there. Maybe we should be using router.use() instead. http://expressjs.com/4x/api.html#router
Yes, it does not seem to work in the service setup. I think the problem is route duplication. get('/app/:id') route is overriding my new get('/app/count') route.
I tried to use app.param with regex using this but it does not work in service setup.
Only it works when you can define count route before the todos service initialization.
var feathers = require('../lib/feathers');
var TodoService = require('./todos');
var app=feathers();
app.param(function(name, fn){
if (fn instanceof RegExp) {
return function(req, res, next, val){
var captures;
if (captures = fn.exec(String(val))) {
req.params[name] = captures;
next();
} else {
next('route');
}
}
}
});
app.param('id', /^\d+$/);
app.get('/todos/count', function(req, res) {
TodoService.count(function(error, data) {
res.end(JSON.stringify(data));
});
});
app.configure(feathers.rest())
.use(feathers.static(__dirname))
.use('/todos', TodoService)
.listen(8080);
That's what I thought. It's because the :id route gets hit before the other one. The solution is probably registering the service REST routes after service.setup is called on app.setup.
I'm working on a solution for this. Hope to have a PR ready for review tomorrow.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
Most helpful comment
Having a method like that is not very RESTful (I'd probably try to use the HTTP range header) but it is still easy to add as a custom middleware in the services
.setup:Another option would be for
.findto return an object instead of an array that contains counting information and add a params flag that allows you to only retrieve that: