Express: req.route undefined when using app.use()

Created on 21 Feb 2020  路  11Comments  路  Source: expressjs/express

The documentation for req.path says:

app.get('/user/:id?', function userIdHandler (req, res) {
  console.log(req.route)
  res.send('GET')
})

// Gives
{ path: '/user/:id?',
  stack:
   [ { handle: [Function: userIdHandler],
       name: 'userIdHandler',
       params: undefined,
       path: undefined,
       keys: [],
       regexp: /^\/?$/i,
       method: 'get' } ],
  methods: { get: true } }

However, there is no indication that req.use should not work with this. http://expressjs.com/en/guide/using-middleware.html clearly states that even in the cases of using .use the term "path" is still used for where you mount.

question

All 11 comments

The path you see in your output is req.route.path since you are printing req.route. To see req.path you should console.log(req.path).

@dougwilson I just verified this again. I am doing the following in a middleware:

console.log(req.route);

The only difference between my invocations is that first I use app.all() and then change it to app.use(). In the first case req.route is defined, in the second case req.route returns undefined.

The req.route is only for routes, not for middleware. That is why when you change your declaration from a route (app.all) to a middleware (app.use) it is no longer there.

@dougwilson Is it a fair feature request to ask that it is part of app.use? There is on indication in the docs that it should be:

Contains the currently-matched route, a string. For example:

A route (or route path) is also part of a middleware.

(I digress, a "middleware" is also used in app.all according to your own docs: https://expressjs.com/en/guide/writing-middleware.html - see the picture where it says "app.get" but the whole document is about "Writing middleware", or see my previous topic on this)

Hi @thernstig , no, it is not a fair feature request. That is a distinguishing feature between middlewares and routes; routes (like app.all) have a route (visible in req.route) and middlewares do not have a route... If you wanted a route, why not use app.all if that fits your use case?

(I digress, a "middleware" is also used in app.all according to your own docs: https://expressjs.com/en/guide/writing-middleware.html - see the picture where it says "app.get" but the whole document is about "Writing middleware", or see my previous topic on this)

There is a lots of issues in our documentation around terminology, as it has been written and changed by many people to the best efforts. The source of trust is how it is functioning. If we need to update docs or make it clearer, please open up issues on the website so we can make it happen.

But everything said so far Express is working just as designed, and it sounds like this is commentary more on the wording and definitions in the documentation, which we can definately work to correct.

The reason "middleware" is also used in app.all is because a route can also contain middleware, just like an ap; it is all the functions before your final handler in the route: app.all('/foo', middleware1, middleware2, fooHandler).

The _route_ is not the passed in function, rather it is the mechanism of app.all and what happens behind the scenes.

A route is an actual object, which you can make directly using app.route, but we provide short hands like app.all and app.get which will create a route object and add your functions to it for you; app.use never create any route objects at all, so would have no route objects to provide to you...

Thanks for the elaborate explanation. That gave some context to it. For reference, my use case was to do something like:

// Here I wanted to check req.route.path before the call to next()
// I.e. I wanted to handle it for all route paths
app.use('/api/user/', (req) => {do_something; next();})
app.get('/api/user/')
app.get('/api/user/:username')
app.get('/api/user/fo/moo')
app.get('/api/user/foo/moo/:random')
app.get('/api/user/chocolate/honey')
...
x 20
...

I did not want to do it per route because I wanted to apply a regex that would work for all added methods for the /api/user and all sub-paths. I will have to solve this some other way then.

It's no problem. And we are always here to help answer even specific things like "how would I do X in Express?" mainly because the act of going though the process both helps teach "Express-isms" as well as can provide insight into changes needed in Express.

From what you gave above, I assume that the do_something is where you wanted to check req.route.path? Would it not just always === '/api/user' in your example, if a route was created for app.use calls? Your do_something in your example is already only ever called when the req.path starts with /api/user/, so I guess, I'm not clear on what you're thinking of checking within that block?

That is correct, it was in do_something I wanted to check req.route.path.

Wouldn't app.use('/api/user') would also match '/api/user/:username', '/api/user/fo/moo' and not only '/api/user'? So if a route was created for app.use calls I was guessing it would equal the exact route the user did in the HTTP request?

Wouldn't app.use('/api/user') would also match '/api/user/:username', '/api/user/fo/moo' and not only '/api/user'?

That's right, as app.use is based on a prefix-match, where as routes are based on a full-path-match. Thus app.use('/api/user/') would match all paths and methods that start with /api/user/, where as a route like app.all('/api/user/') would only match the specific path of /api/user/.

So if a route was created for app.use calls I was guessing it would equal the exact route the user did in the HTTP request?

Right, if a route was created, it would be an exact match, but app.use doesn't create a route, instead that is using prefix-matching. app.all would create a router underneath the call, so would then only work for the exact match.

Yepp, got it now 馃槂 馃憤 Will ponder on a better solution to my problems.

I'm later in this conversation.
in our case middleware needs to know to which route request is going to but attaching it to every route or writing our own regex doesn't sound reasonable.

is there a way to call the "parsing" function from the Router to figure out from request URL what route it would be?
I can add such a call easily. People would be able to "parse" route if use-case needs it still keeping default behavior intact.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

despairblue picture despairblue  路  3Comments

cuni0716 picture cuni0716  路  3Comments

jefflage picture jefflage  路  4Comments

afanasy picture afanasy  路  3Comments

wxs77577 picture wxs77577  路  3Comments