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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With