multiple routes with differents params, calling th

2019-09-01 01:48发布

问题:

Is it possible with expressjs to have multiple routes calling the same resource, something like that:

app.get('/users/:user_id', users.getOne)
app.get('/users/:username', users.getOne)

I would like to be able to call users.getOne whichever params (:user_id or :username) is used in the get request.

In the users.getOne function, how can I determine wich one was used and build my query according to it?

exports.getOne = function(req, res){

  var queryParams = ? // I need help here

  Users
    .find(queryParams)
    ...

Thanks!

Possibly related: express.js - single routing handler for multiple routes in a single line

回答1:

Those are in fact, from express's view, the same route.

No, they are not. One route has :user_id parameter, another one has :username.

This would be a proper solution:

var OBJECT_ID_RE = /^[a-f\d]{24}$/i;

app.param('user_id', function(req, res, next, value, name) {
  if (OBJECT_ID_RE.test(value)) {
    next()
  } else {
    next('route')
  }
})

app.get('/users/:user_id', users.getOne)
app.get('/users/:username', users.getOne)

app.param set the prerequisite for the route to be called. This way when user_id matches a pattern, first route gets called, otherwise second one.



回答2:

From express's view, both of those routes will match the same set of request URLs. You only need one of them and you can name it to make more sense:

app.get('/users/:key', users.getOne);

//...
// http://stackoverflow.com/a/20988824/266795
var OBJECT_ID_RE = /^[a-f\d]{24}$/i;
exports.getOne = function(req, res) {
  var conditions = {_id: req.params.key};
  if (!OBJECT_ID_RE.test(req.params.key)) {
    conditions = {username: req.params.key};
  }
  Users.find(conditions)...

If you end up wanting this pattern in many routes throughout your code base, you can extract it into a /users/:user param and use app.param as per @alex's answer, but encapsulate the code to locate the user and stick it on to req.user so the actual route handler can just assume the user has been properly found and loaded by the time it executes, and 404 handling can be centralized as well.