javascript - ExpressJS req.params empty in nested routers - Stack Overflow

I use a routing setup that uses my 'api' folder's dir structure to intuitively set up th

I use a routing setup that uses my 'api' folder's dir structure to intuitively set up the routes. However, in cases where I use a folder name to represent a route parameter, req.params is undefined in the controller.

The route with the problem is:

GET /api/google/accounts/:account_id/analytics/profiles/

Here is my route loader. It basically does a glob on the api folder looking for files named routes.js and does app.use on the appropriate route (determinited from the folder structure).

  // load routers
  files = glob.sync("api/**/routes.js");

  console.log(files);
  // [ 'api/campaigns/routes.js',
  //   'api/google/accounts/:account_id/analytics/profiles/routes.js',
  //   'api/google/accounts/routes.js',
  //   'api/google/urls/routes.js',
  //   'api/users/routes.js' ]

  // use each router on the appropriate route
  for(var i=0;i<files.length;i++) {

    route  = "/" + files[i].split("/routes.js")[0];

    console.log(route);
    // '/api/google/accounts/:account_id/analytics/profiles'

    router = require(path.join(__dirname, files[i]))(config);
    routes = router.stack;
    app.use(route, router);

    // list all registered routes for this router
    for(var j=0;j<routes.length;j++) {
      routeDebug(("      " + Object.keys(routes[j].route.methods)[0].toUpperCase()).slice(-6) + " " + route + routes[j].route.path);
    }
  }

The 'api' folder structure is:

./api
./api/campaigns
./api/campaigns/controller.js
./api/campaigns/model.js
./api/campaigns/routes.js
./api/users
./api/users/controller.js
./api/users/model.js
./api/users/routes.js
./api/google
./api/google/accounts
./api/google/accounts/:account_id
./api/google/accounts/:account_id/analytics
./api/google/accounts/:account_id/analytics/profiles
./api/google/accounts/:account_id/analytics/profiles/controller.js
./api/google/accounts/:account_id/analytics/profiles/routes.js
./api/google/accounts/controller.js
./api/google/accounts/model.js
./api/google/accounts/routes.js
./api/google/urls
./api/google/urls/controller.js
./api/google/urls/routes.js

In the above loop, routeDebug is a wrapper around the debug npm package. Output is:

  routes    GET /api/campaigns/ +0ms
  routes   POST /api/campaigns/ +2ms
  routes    GET /api/campaigns/:campaign_id +1ms
  routes    PUT /api/campaigns/:campaign_id +0ms
  routes DELETE /api/campaigns/:campaign_id +0ms
  routes    GET /api/google/accounts/:account_id/analytics/profiles/ +128ms
  routes    GET /api/google/accounts/ +4ms
  routes   POST /api/google/accounts/ +0ms
  routes   POST /api/google/urls/ +3ms
  routes    GET /api/users/ +12ms
  routes   POST /api/users/ +0ms
  routes    GET /api/users/:user_id +0ms
  routes    PUT /api/users/:user_id +0ms
  routes DELETE /api/users/:user_id +0ms

So we can see that the route in question is being set up as expected. But req.params is undefined. Other routes don't have this problem.

Why is req.params empty only for this particular route? Is there a better way to get these nested routes built than using a folder as a route param?

EDIT: I expect that the issue stems from nested routers not being able to access parent routers' params.

Rest with Express.js nested router

However, setting up the child router as suggested doesn't help either.

var router = require("express").Router({mergeParams: true});
// no difference

I use a routing setup that uses my 'api' folder's dir structure to intuitively set up the routes. However, in cases where I use a folder name to represent a route parameter, req.params is undefined in the controller.

The route with the problem is:

GET /api/google/accounts/:account_id/analytics/profiles/

Here is my route loader. It basically does a glob on the api folder looking for files named routes.js and does app.use on the appropriate route (determinited from the folder structure).

  // load routers
  files = glob.sync("api/**/routes.js");

  console.log(files);
  // [ 'api/campaigns/routes.js',
  //   'api/google/accounts/:account_id/analytics/profiles/routes.js',
  //   'api/google/accounts/routes.js',
  //   'api/google/urls/routes.js',
  //   'api/users/routes.js' ]

  // use each router on the appropriate route
  for(var i=0;i<files.length;i++) {

    route  = "/" + files[i].split("/routes.js")[0];

    console.log(route);
    // '/api/google/accounts/:account_id/analytics/profiles'

    router = require(path.join(__dirname, files[i]))(config);
    routes = router.stack;
    app.use(route, router);

    // list all registered routes for this router
    for(var j=0;j<routes.length;j++) {
      routeDebug(("      " + Object.keys(routes[j].route.methods)[0].toUpperCase()).slice(-6) + " " + route + routes[j].route.path);
    }
  }

The 'api' folder structure is:

./api
./api/campaigns
./api/campaigns/controller.js
./api/campaigns/model.js
./api/campaigns/routes.js
./api/users
./api/users/controller.js
./api/users/model.js
./api/users/routes.js
./api/google
./api/google/accounts
./api/google/accounts/:account_id
./api/google/accounts/:account_id/analytics
./api/google/accounts/:account_id/analytics/profiles
./api/google/accounts/:account_id/analytics/profiles/controller.js
./api/google/accounts/:account_id/analytics/profiles/routes.js
./api/google/accounts/controller.js
./api/google/accounts/model.js
./api/google/accounts/routes.js
./api/google/urls
./api/google/urls/controller.js
./api/google/urls/routes.js

In the above loop, routeDebug is a wrapper around the debug npm package. Output is:

  routes    GET /api/campaigns/ +0ms
  routes   POST /api/campaigns/ +2ms
  routes    GET /api/campaigns/:campaign_id +1ms
  routes    PUT /api/campaigns/:campaign_id +0ms
  routes DELETE /api/campaigns/:campaign_id +0ms
  routes    GET /api/google/accounts/:account_id/analytics/profiles/ +128ms
  routes    GET /api/google/accounts/ +4ms
  routes   POST /api/google/accounts/ +0ms
  routes   POST /api/google/urls/ +3ms
  routes    GET /api/users/ +12ms
  routes   POST /api/users/ +0ms
  routes    GET /api/users/:user_id +0ms
  routes    PUT /api/users/:user_id +0ms
  routes DELETE /api/users/:user_id +0ms

So we can see that the route in question is being set up as expected. But req.params is undefined. Other routes don't have this problem.

Why is req.params empty only for this particular route? Is there a better way to get these nested routes built than using a folder as a route param?

EDIT: I expect that the issue stems from nested routers not being able to access parent routers' params.

Rest with Express.js nested router

However, setting up the child router as suggested doesn't help either.

var router = require("express").Router({mergeParams: true});
// no difference
Share Improve this question edited May 23, 2017 at 11:53 CommunityBot 11 silver badge asked Mar 17, 2015 at 15:07 mz3mz3 1,34412 silver badges28 bronze badges 2
  • Are you using body-parser? – Josh1billion Commented Mar 17, 2015 at 15:13
  • Yes, other routes are able to access req.params no problem. I'll add one more detail to the end of the question. – mz3 Commented Mar 17, 2015 at 15:15
Add a ment  | 

1 Answer 1

Reset to default 10

It turns out mergeParams was not added to Express until 4.5.0; my project was still on 4.2.0. Updating to 4.5.0 and passing {mergeParams: true} to the child router solved the issue. See this similar question for more details:

Rest with Express.js nested router

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744145448a4560399.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信