0

According to the docs for express, the path parameter is optional for app.use, so to apply the middleware to any incoming request you can write:

app.use(function (req, res, next) {
  res.send('ANY request');
  next();
});

But for app.get the path parameter is apparently not optional, so to apply the middleware to any incoming GET request you have to write:

app.get('/', function (req, res, next) {
  res.send('GET request');
  next();
});

But I find that it doesn't complain if I do miss out the path:

app.get(function (req, res, next) {
  res.send('GET request');
  next();
});

So, are the above two definitions equivalent, or is the second one doing something different to the first one?

I'm also not sure of the difference between specifying / or * as the path:

app.get('*', function (req, res, next) {
  res.send('GET request');
  next();
});

So, in summary, is there any difference between app.get('/', fn) and app.get('*', fn) and app.get(fn)?

drmrbrewer
  • 11,491
  • 21
  • 85
  • 181

1 Answers1

1

Somewhat confusingly, there are two methods called app.get:

https://expressjs.com/en/4x/api.html#app.get

One is the converse to app.set, the other is the one for handling GET requests. In practice JS only allows a single method, so internally Express checks how many arguments are passed to work out which one you meant:

https://github.com/expressjs/express/blob/351396f971280ab79faddcf9782ea50f4e88358d/lib/application.js#L474

So while using app.get(fn) might not complain, it won't actually work as a route because it'll be treating it as the other form of get.

The difference between app.get('*', ...) and app.get('/', ...) is that the * will match any path whereas / will only match the exact path / (and nothing more). This is different from app.use, where the path is treated like a 'starts with'.

You may find the answer I gave here helpful to understand how paths differ between get and use: Difference between app.use and app.get *in proxying*.

skirtle
  • 27,868
  • 4
  • 42
  • 57
  • Thanks. I saw the other single-argument `app.get` but thought that, with some type-checking at the top of the function, it could maybe distinguish between a string and a function passed in, and treat the latter as a catch-all route... equivalent to `app.get('*', fn)`... but that isn't the case? And as for the difference between `*` and `/` I was thoroughly thrown off track by `app.use` where, like you say, `/` is treated like 'starts with'... very confusing that it is different to `app.get('/', fn)`! – drmrbrewer Nov 21 '17 at 09:59
  • 1
    `app.get`, `app.post`, etc. all work the same way, they all require a path. If you read through the source code you'll see that they all just pass through to an internal router, which calls `router.route` with the path. Nowhere is a default path applied. I imagine that part of the reason for this is that there isn't a particularly good default choice for the path. For middleware (`app.use`) it makes sense to default to 'everything' but for routes registered with `app.get`, etc. it's much less common to want to match 'everything'. I agree it would be helpful if `app.get` did a type-check. – skirtle Nov 21 '17 at 10:16