I came across this situation where the middleware of the root path in ExpressJS gets executed at each request. I have the following code:
app.use('/', nr_one, require('./routes/index'));
app.use('/about', nr_two, require('./routes/about'));
app.use('/help', nr_three, require('./routes/help'));
function nr_one(req, res, next)
{
console.log('Nr 1');
next();
}
function nr_two(req, res, next)
{
console.log('Nr 2');
next();
}
function nr_three(req, res, next)
{
console.log('Nr 3');
next();
}
This what happens in my log for each route:
10:31:21 AM web.1 | Nr 1
10:31:21 AM web.1 | Index
10:31:21 AM web.1 | GET / 304 7.543 ms - -
10:33:01 AM web.1 | Nr 1
10:33:01 AM web.1 | Nr 2
10:33:01 AM web.1 | About
10:33:01 AM web.1 | GET /about 200 108.216 ms - 1585
10:34:56 AM web.1 | Nr 1
10:34:56 AM web.1 | Nr 3
10:34:56 AM web.1 | Help
10:34:56 AM web.1 | GET /help 304 24.246 ms - -
After talking with a friend we discovered that this happens on version:
I'm on Debian, he is on Windows.
Hi @davidgatti my "root path middlware" I assume you are talking about nr_one. If so, yes, of course it is executed on every request; app.use is a prefix-match system. Every URL starts with /, so anything mounted at / will of course get executed :)
If you want exact path matching, you should be using app.METHOD or app.all.
Let me know if the following documentation help, or should be improved:
app.use documentation: http://expressjs.com/en/4x/api.html#app.use
app.METHOD documentation: http://expressjs.com/en/4x/api.html#app.METHOD
app.all documentation: http://expressjs.com/en/4x/api.html#app.all
hmm.. so you are saying that /about is matching /? Because my thinking here is /about is a very specific path, and should not match /. Rrrright....
Hi @davidgatti well, you put app.use('/', fn) above that route. That means that if /about starts with /, it will run still (which yes, it does start with /). The app.use is a prefix-match system. Every URL starts with /, so anything mounted at / will of course get executed :) If you want exact path matching, you should be using app.METHOD or app.all.
OK, my brain interprets /about differently then / to me those are unequal ;) So at least this is my thinking process here.
About the documentation:
Mounts the specified middleware function or functions at the specified path:
Again, /about is differently then / to me... the human ;)
the middleware function is executed when the base of the requested path matches path.
This is what you are referring to, but to me this doesn't explain the situation. But now that I think about it, a friend yesterday got this idea right, meaning it was his first thought when we were discussing this, but to me it didn't make sense. So I wonder what is the difference in our brains. Hmm....
One more thing just to point out based on what you wrote:
/ root path has the slash and matches /about because also starts with a /. Then why when I visit /help, /about is not triggered? All 3 stat with a /.
Hi @davidgatti it's certainly possible. This is how Express is meant to behave. If you have ideas for how to improve the docs, at the bottom of every page on our site, you can find a "Edit this page on GitHub." which will let you make proposals for any doc changes :)
Then why when I visit /help, /aboutis not triggered? All 3 stat with a/`.
Because /help does not start with /about :)
Whaaaa? :D OK, could you be so kind, and point me to the line of code or section that is responsible for this? I thinking how to improve the doc, but still I don't fully understand the situation :) it is so un-logical to me :) - not meant to offend, just stating how my brain is thinking right now.
Hi @davidgatti the magic happens with this line: https://github.com/expressjs/express/blob/master/lib/router/index.js#L467
I thinking how to improve the doc, but still I don't fully understand the situation :) it is so un-logical to me :) - not meant to offend, just stating how my brain is thinking right now.
It's no problem at all! The code has been this way since ~2009, and from all this time, I'm not sure I've ever personally answered this question, so really had no idea the docs were lacking in this regard or it was confusing. People think in different ways, and that's OK -- it's pretty much the main reason we really like it when we get docs PRs because when it makes sense to us, it's hard to understand how it wouldn't make sense to someone else, if that makes sense.
Defiantly, and I'll try to see if I can come up with something, to save the next weird person that will come in 8 years :D
@davidgatti I think you are confusing the use of .use(path, ...) and .get(path, ...).
.use is for middleware. In this case, Router is a type of middleware that holds many paths.
So, "use this middleware on any path that starts with / "
or "use this middleware on any path that starts with /about ".
Where as .get, .post, ....etc, are "use this handler (and/or middleware) on this exact path" .
@WORMSS ooo, I got your point, stupid me, but some how I didn't put the two tighter when it comes the the require('./routes/index') part, now it looks obvious. But still the matching / is weird to me :)
@dougwilson I've read the docs many times, and yet this particular difference between use and all has always avoided me
I've been using express for years...
anyway, thank you 馃槤