Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding custom method to service #86

Closed
yusufsafak opened this issue Jun 19, 2014 · 9 comments · Fixed by #91
Closed

Adding custom method to service #86

yusufsafak opened this issue Jun 19, 2014 · 9 comments · Fixed by #91
Milestone

Comments

@yusufsafak
Copy link

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

@daffl
Copy link
Member

daffl commented Jun 19, 2014

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);
  }
}

@yusufsafak
Copy link
Author

Thanks a lot.

@daffl daffl closed this as completed Jun 27, 2014
@haohello
Copy link

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?

@daffl
Copy link
Member

daffl commented Jun 28, 2014

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 daffl reopened this Jun 28, 2014
@daffl daffl added this to the 1.0.0 milestone Jul 4, 2014
@ekryski
Copy link
Contributor

ekryski commented Jul 5, 2014

@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

@yusufsafak
Copy link
Author

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);

@daffl
Copy link
Member

daffl commented Jul 6, 2014

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.

@ekryski
Copy link
Contributor

ekryski commented Jul 21, 2014

I'm working on a solution for this. Hope to have a PR ready for review tomorrow.

@daffl daffl mentioned this issue Aug 10, 2014
@daffl daffl closed this as completed in #91 Aug 11, 2014
daffl added a commit that referenced this issue Aug 25, 2018
Add test and fix for generic service
daffl pushed a commit that referenced this issue Aug 29, 2018
* Fix for Update an existing entity in verifier \#18

* Fix merge issue
daffl pushed a commit that referenced this issue Aug 29, 2018
* chore(package): update mocha to version 5.0.0

* Update dependencies
daffl pushed a commit that referenced this issue Aug 29, 2018
* Fix for Update an existing entity in verifier \#18

* Fix merge issue
daffl pushed a commit that referenced this issue Aug 29, 2018
* chore(package): update mocha to version 5.0.0

* Update dependencies
@lock
Copy link

lock bot commented Feb 8, 2019

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.

@lock lock bot locked as resolved and limited conversation to collaborators Feb 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants