How does Express know which Router path to use when multiple paths match?

Say there are 2 router.route(), for example:

router.route('/app/:id').get(funtion(req, res, next){
    console.log("id route")
});

and

router.route('/app/:username').get(funtion(req, res, next){
    console.log("user route")
});

When GET /app/nsuzuki is called, which router.route() does it use and why?

Answers


To fully understand this, please read the documentation: http://expressjs.com/api.html#router.METHOD

How Express Routes Capture Paths

When you use a :param as a part of your path, it matches everything like /*, and the captured value is stored in req.params.param.

When you have more than one rule, the first one registered is the first one checked against. It checks each call against each rule until a match is found. If you call next() with no values passed to it, it will look for the next match (either in the same route, or continue on into the next middleware).

So these three rules will all be run

var handleRoute = function(req, res, next){
   console.log(req.path + ' ' + req.params.id + ' ' + req.params.user + ' ' + req.params[0]);
   next();
}

route.route('/user/:id').get(handleRoute);
route.route('/user/:user').get(handleRoute);
route.route('/user/*').get(handleRoute);

When I request /user/foobar, I'll see the following output (and probably an error as a client because I never responded :P)

/user/foobar foobar undefined undefined
/user/foobar undefined foobar undefined
/user/foobar undefined undefined foobar

It will hit all three, but the context is different for each.

How to Capture Path Patterns with Regular Expressions

If you want to capture separate routes for id (let's say all numbers) and user name (all letters), you can do this:

var handleRoute = function(tag) {
  return function(req, res, next) {
    console.log(tag + ' ' + req.path + ' -> ' + req.params[0]);
    res.status(200)
      .json({
        success: 'yay!'
      });
  };
};

route.route(/^\/user\/([0-9]+)$/i)
  .get(handleRoute('id'));
route.route(/^\user\/([A-Za-z]+)$/i)
  .get(handleRoute('user'));
route.route('/user/*')
  .get(handleRoute('catch all'));

Note the parathesis around my capture group. Without this, params is empty. It auto captures with just * in the string because they are nice folks. I'll get the following for output when I run against the three different types.

id /user/123 -> 123
user /user/user -> user
catch all /user/user.1 -> user.1

All that explained, you're opening yourself up to some vectors for bugs to infest your system. Might want to think about your URL pattern.


Need Your Help

Why is call necessary in this Javascript example?

javascript

Here's the problem (called "Compose functions (T Combinator)" on codewars.com, in case you want to try it out in the original environment):

java: TrayIcon right click disabled on Mac OsX

java macos mouseevent trayicon dispatchevent

I'm trying to develop a Mac OsX app provided by a system tray icon, so after the first attempt with the simplest code to achieve it I noticed that every apps tray icon's (both system and user apps)...