1

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

2 Answers 2

2

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'));
Sign up to request clarification or add additional context in comments.

3 Comments

I suggest you do req._params = req._params || [] then req._params.push(req.params). This way it works with multiple levels of mounting.
Thanks. :) I heard they're going to fix this up in a future release; I really hope so...
@Plato: But then you have an array of objects and you cannot access req._params.test anymore. I updated my answer to reflect multiple levels of mounting.
1

express.js (>= v4.5.0+) provides a direct solution without having to implement middleware. https://expressjs.com/en/api.html#express.router

While creating the router, pass the mergeParams flag.

var router = express.Router({ mergeParams: true })

mergeParams preserves the req.params values from the parent router. If the parent and the child have conflicting param names, the child’s value takes precedence.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.