Skip to content

Be able to create custom routes #93

Closed

Description

@ekryski

I would like to be able to specify what mime types are supported via rest:

app.use('/users', UserService, {
  json: true
});

// which might result in /users.json and /users/1.json being the routes

and also create namespaced routes:

app.use('/users', UserService, {
  json: true,
  prefix: 'api'
});

// which might result in /api/users.json and /api/users/1.json being the routes

Similar idea to #86 but I don't think using the .setup() method is elegant or efficient.

Activity

  1. daffl commented on Sep 2, 2014

    @daffl
    Member

    I'm not sure the prefix is necessary. Why couldn't you just do

    app.use('/api/users', UserService);

    Or create a separate app and use it on a different route (as done with the new Testee):

    var api = feathers().use('/users', UserService);
    
    // Map that app to /api (will provide /api/users)
    var app = feathers().use('/api', api);
    

    As for the content type, Express does allow REST content negotiation, for Feathers like:

    app.configure(feathers.rest(function restFormatter(req, res) {
      res.format({
        'text/plain': function() {
          res.end('The todo is: ' + res.data.description);
        },
        'application/json': function() {
          res.json(res.data);
        }
      });
    }));

    I don't think you can use file name extensions this way but setting the Accept HTTP header should be possible with every client.

  2. ekryski commented on Sep 2, 2014

    @ekryski
    ContributorAuthor

    Or create a separate app and use it on a different route (as done with the new Testee):

    Very clever Dave 😉. Totally didn't think of that one.

    As for content negotiation say I want to render out a specific template. For example I hit the /users endpoint and I want to render out the 'users' template for html. When I tried that I actually didn't have access to the request object and therefore wasn't able to determine the path.

  3. daffl commented on Sep 2, 2014

    @daffl
    Member

    I would keep that separate from the service though. In the negotiator it would be

    app.configure(feathers.rest(function restFormatter(req, res) {
      res.format({
        'text/html': function() {
          var template = req.url;
          res.render('/views/' + template, res.data);
        },
    
        'application/json': function() {
          res.json(res.data);
        }
      });
    }));

    The view information could also be added with a custom middleware:

    app.use('/users', function(req, res, next) {
      req.view = 'views/user.jade';
      next();
    }, UserService);
  4. ekryski commented on Sep 2, 2014

    @ekryski
    ContributorAuthor

    Yep that works pretty well and what I had tried. For some reason my req.path is not right so I need to grab req.route.path.

    Regardless, the solution is good but it gets complicated when you have urls like /users/:id and you want to res.render('user', {data: res.data}). Possibly namespacing your feathers routes and declaring your own html route handlers might be the best solution for separating JSON/XML routes from HTML ones.

    Otherwise you end up writing some janky logic to determine which template should be rendered based on the route path. This could get really complicated if you have stuff like /users/:id/subscriptions, as an example.

  5. agonbina commented on Oct 9, 2014

    @agonbina

    @daffl In the case where you have

    var api = feathers().use('/users', UserService);
    var app = feathers().use('/api', api);
    

    do configurations from app apply to the api instance too?
    Ex. if I have

    app.configure(feathers.rest())
    .use(bodyParser.json())
    .use(...other feather instances ...)
    

    , do we still need to do the same for api or since we have applied those configs before 'mounting' api they would apply to it as well?

    Thanks!

  6. daffl commented on Oct 9, 2014

    @daffl
    Member

    I don't think so. Every Express application has its individual middleware stack. The easiest way is probably to put common middleware into a separate setup function and .configure it on each application:

    function setup() {
      var app = this;
    
      app.configure(feathers.rest())
        .use(bodyParser.json())
    }
    
    app.configure(setup);
    api.configure(setup);
  7. agonbina commented on Oct 9, 2014

    @agonbina

    Yep, just tried leaving out configuration for the api and it no longer works as expected, so definitely each instance has its own middleware stack.

    Thanks for the quick response!

  8. daffl commented on Dec 16, 2014

    @daffl
    Member

    I think we can close this issue? If there is still things to think about I'd put them in a new one. I worked with a Feathers app that had some static pages and didn't run into any hard problems connecting services and rendering static pages.

  9. lock commented on Feb 8, 2019

    @lock

    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.

  10. locked as resolved and limited conversation to collaborators on Feb 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions