Skip to content
This repository has been archived by the owner on Jan 25, 2020. It is now read-only.

Feature Request: Dynamic parameter handling for directories #35

Open
jgable opened this issue May 18, 2014 · 15 comments
Open

Feature Request: Dynamic parameter handling for directories #35

jgable opened this issue May 18, 2014 · 15 comments

Comments

@jgable
Copy link

jgable commented May 18, 2014

I'm often in situations where I'd like to be able to separate out some deeply nested routes based on a root/:param type of situation.

Here are some example routes to illustrate the points:

  • /api/projects
  • /api/projects/:taskId
  • /api/projects/:taskId/team
  • /api/projects/:taskId/team/:teamId

Right now, I'd have one big index.js file in the /api/projects directory for all those routes. What do you think about a structure like this:

/api
  /projects
    index.js
    /_taskId
      index.js
      /team
        index.js
        /_teamId
          index.js

Basically, directories with a leading _ would be converted to parameter routes. I mean, I'll admit it gets a little deep directory wise. But, you could always still just put everything right in the index.js. I think coupled with some CLI tooling/generators this wouldn't be that bad to whip out deep API handlers pretty quickly.

@totherik
Copy link
Member

Interesting idea. I'll let others comment, too, but I need a little while to think on this. Just so you know you should also be able to do something like this (if it helps):

/api/projects.js
'use strict';

// api/projects.js
module.exports = function projects(router) {

    router.get('/', function (req, res) {
        res.send('ok');
    };

    router.get('/:taskId', function (req, res) {
        res.send('ok');
    };

    router.get('/:taskId/team', function (req, res) {
        res.send('ok');
    };

    router.get('/:taskId/team/:teamId', function (req, res) {
        res.send('ok');
    };

}

Also, if you need it, this version of enrouten allows you to generate urls. Here's a (contrived) example:

router.get({ name: 'projectById', path: '/:taskId' }, function (req, res) {
    res.send('ok');
};

router.get({ name: 'projectTeams', path: '/:taskId/team' }, function (req, res) {
    var task, team, data;

    // get task and teams from somewhere

    data = {
        project: {
            id: task.id,
            uri: req.app.locals.enrouten.path('projectById', { taskId: task.id }),
            teams: [{
                id: team.id,
                uri: req.app.locals.enrouten.path('projectTeamById', { taskId: task.id, teamId: team.id })
            }]
        }    
    };

    res.json(data);
};

router.get({ name: 'projectTeamById', path: '/:taskId/team/:teamId'}, function (req, res) {
    res.send('ok');
};

@alexander-heimbuch
Copy link

That's a really nice idea. Currently I'm looking for a dynamic routing prefix. The underscored approach could be a good solution.

@erikmueller
Copy link

👍 Like the underscore idea for dynamic folders.

@tkambler
Copy link

Yes, please. 👍

@jgable
Copy link
Author

jgable commented Jul 23, 2014

For what it's worth, I've since changed my API design to have less deeply nested routes so this isn't really applicable to me any more. But, it looks like others might find it useful.

@afloyd
Copy link

afloyd commented Jul 28, 2014

I love the idea of enrouten. I have been using my "file-magik" module to auto-require/include all my routing files. But I was looking more after learning about express.Router() a while back, and enrouten almost had everything. But the route params feature was something I wanted/needed too.

Then I realized with just a few changes (which ended up being it's own module) I could use my existing module to do just what I was looking for. It doesn't have some of the bells and whistles of this project, but does have some this one doesn't... I wrote this quick and dirty module yesterday/today

Check it out if interested: https://github.com/afloyd/express-routify

@aredridel
Copy link

@tlivings should probably chime in here.

@tlivings
Copy link
Member

So, I've done something similar to this over at swaggerize-express.

Since I am working off of swagger documents, path params are of the form {param} in the directory structure.

Example:

handlers
  |--users
  |    |--{id}.js
  |    |--{id}
  |        |--foo.js

This will map as:

/users/{id}
/users/{id}/foo

I considered index.js but decided against it since it didn't play well with subresources and index is a valid path name in a url.

@tlivings
Copy link
Member

PS: If there is no subresource, the above example would be simplified to:

handlers
  |--users
  |    |--{id}.js

I'd personally like to remove index.js from express-enrouten as well.

@sixlettervariables
Copy link

@tlivings: in your model /users would be handled by ./handlers/users.js rather than ./handlers/users/index.js, correct? Going with that approach my question for the express-enrouten side would be how would you handle the root route?

@tlivings
Copy link
Member

Yes, that's true. For RESTful services, there will always be a resource. For an application, there can be a root route, so it might not be possible to do away with index.js.

@aredridel
Copy link

/ is a perfectly acceptable path for a resource in a REST service too!

@tlivings
Copy link
Member

There may not be anything stopping one from exposing resources at / but I think it goes against convention of how resources are typically represented. We can argue offline though 😸

@felipeleusin
Copy link

+1. I've been making some tests with this and it works ok, you have to remember to initialize the Router with { mergeParams: true } for this to work.

@blowsie
Copy link

blowsie commented Oct 2, 2019

late to the party here, but Nuxt has this style of routing

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests