Search code examples
javascriptnode.jsexpressurl-routing

Express js get parameters from root of URL (Not as simple as req.params)


I've made an api and I've routed it as follows:

In the main routes file:

  //with sub-route
  app.use('/api/test/:test', require('./api/test'));

  //Without sub-route
  app.use('/api/test2/:test', function(req, res){
    console.log('in test', req.params, req.body);
    return res.status(200).json({params: req.params, body: req.body});
  });

Accessing the second route displays the :test in req.params, as expected.

In the modular routes folder ('./api/test') I have a sub-router (index.js) which looks like this:

router.get('/:test2', controller.getItem);

with a handler:

exports.getItem = function getItem(req, res) {
  console.log('in getItem \nreq.params', req.params, '\nreq.body: ', req.body);
  return res.status(200).json({yes: 'yes', params: req.params, body: req.body});
};

So the first url, which has no sub-routing is: /api/test2/:test and logs out whatever you put in place of :test in req.params.

The second url, which has sub-routing is: /api/test/:test/:test2, but when you send your get request only :test2 appears in req.params.

It seems that if you use this pattern any variables in the 'root' of the route (ie in the primary router) are not picked up.

Is there a way to fix this?

Thanks


Solution

  • You will need a middleware to fix this for you:

    function paramFix(req, res, next) {
        req._params = req.params;
        next();
    }
    app.use('/api/test/:test', paramFix, require('./api/test'));
    

    And then use req._params.test in your last callback function.

    So reflect multiple levels of mounting you can extend your middleware like this:

    function paramFix(req, res, next) {
        req._params = req._params || {};
        for (var key in req.params) {
            if (req.params.hasOwnProperty(key)) {
                req._params[key] = req.params[key];
            }
        }
        next();
    }
    app.use('/api/test/:test', paramFix, require('./api/test'));