chovy
chovy

Reputation: 75666

how to get request path with express req object

I'm using express + node.js and I have a req object, the request in the browser is /account but when I log req.path I get '/' --- not '/account'.

  //auth required or redirect
  app.use('/account', function(req, res, next) {
    console.log(req.path);
    if ( !req.session.user ) {
      res.redirect('/login?ref='+req.path);
    } else {
      next();
    }
  });

req.path is / when it should be /account ??

Upvotes: 255

Views: 296764

Answers (11)

TalESid
TalESid

Reputation: 2514

This can produce different results when calling directly in base module i.e. main file (e.g. index.js or app.js) vs calling from inside module via app.use() middleware i.e. route file (e.g. routes/users.js).

API call:
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en

We'll be comparing our outputs against above API call


First, we'll see the result from innner module:

  1. We'll be placing our user module inside routes directory, with one route i.e. /profile/:id/:details

    routes/users.js file

    const router = (require('express')).Router();
    
    router.get('/profile/:id/:details', (req, res) => {
    
        console.log(req.protocol);        // http or https
        console.log(req.hostname);        // only hostname without port
        console.log(req.headers.host);    // hostname with port number (if any); same result with req.header('host')
        console.log(req.route.path);      // exact defined route
        console.log(req.baseUrl);         // base path or group prefix
        console.log(req.path);            // relative path except query params
        console.log(req.url);             // relative path with query|search params
        console.log(req.originalUrl);     // baseURL + url
    
        // Full URL
        console.log(`${req.protocol}://${req.header('host')}${req.originalUrl}`);
    
        res.sendStatus(200);
    
    });
    
    module.exports = router;
    
  2. Now we'll import this user module in main module of the application and add /api/users as base path for user module using app.use() middleware

    index.js file

    const app = (require('express'))();
    
    const users = require('./routes/users');
    app.use('/api/users', users);
    
    const server = require('http').createServer(app);
    server.listen(8000, () => console.log('server listening'));
    

Output

[req.protocol] ............. http
[req.hostname] .......... localhost
[req.headers.host] ..... localhost:8000
[req.route.path] .......... /profile/:id/:details
[req.baseUrl] .............. /api/users
[req.path] ................... /profile/123/summary
[req.url] ...................... /profile/123/summary?view=grid&leng=en
[req.originalUrl] .......... /api/users/profile/123/summary?view=grid&leng=en

Full URL:
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en


Now, we'll see result if we add routes directly in main module:

  1. We'll define our route right in the main module (i.e. app.js or index.js) and concatenate base path /app/users with route path instead of using middleware. So route will become /api/users/profile/:id/:details

    index.js file

    const app = (require('express'))();
    
    app.get('/api/users/profile/:id/:details', (req, res) => {
    
        console.log(req.protocol);        // http or https
        console.log(req.hostname);        // only hostname without port
        console.log(req.headers.host);    // hostname with port number (if any); same result with req.header('host')
        console.log(req.route.path);      // exact defined route
        console.log(req.baseUrl);         // base path or group prefix
        console.log(req.path);            // relative path except query params
        console.log(req.url);             // relative path with query|search params
        console.log(req.originalUrl);     // baseURL + url
    
        // Full URL
        console.log(`${req.protocol}://${req.header('host')}${req.originalUrl}`);
    
        res.sendStatus(200);
    
    });
    
    const server = require('http').createServer(app);
    server.listen(8000, () => console.log('server listening'));
    

Output

[req.protocol] ............. http
[req.hostname] .......... localhost
[req.headers.host] ..... localhost:8000
[req.route.path] .......... /api/users/profile/:id/:details
[req.baseUrl] ..............
[req.path] ................... /api/users/profile/123/summary
[req.url] ...................... /api/users/profile/123/summary?view=grid&leng=en
[req.originalUrl] .......... /api/users/profile/123/summary?view=grid&leng=en

Full URL:
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en

We can clearly see in above output that the only difference is of baseUrl which is empty string here. So, the originalUrl also changes & looks same as the url

Upvotes: 22

mrbridge
mrbridge

Reputation: 11

When using a middleware in express, your request object has several properties you can use to get the correct path:

  • req.baseUrl: /api/account
  • req.originalUrl: /api/account
  • req._parsedUrl.path: /account
  • req._parsedUrl.pathname: /account
  • req._parsedUrl.href: /account
  • req._parsedUrl._raw: /account

PLEASE NOTE: This applies to middlewares

Upvotes: 1

Ciabaros
Ciabaros

Reputation: 2159

Here is an example expanded from the documentation, which nicely wraps all you need to know about accessing the paths/URLs in all cases with express:

app.use('/admin', function (req, res, next) { // GET 'http://www.example.com/admin/new?a=b'
  console.dir(req.originalUrl) // '/admin/new?a=b' (WARNING: beware query string)
  console.dir(req.baseUrl) // '/admin'
  console.dir(req.path) // '/new'
  console.dir(req.baseUrl + req.path) // '/admin/new' (full path without query string)
  next()
})

Based on: https://expressjs.com/en/api.html#req.originalUrl

Conclusion: As c1moore's answer states, use:

var fullPath = req.baseUrl + req.path;

Upvotes: 109

Omar Dulaimi
Omar Dulaimi

Reputation: 1189

For those getting undefined from req.route.path that is correct.

Inside route handler, there's a route. Inside middleware handlers, there's no route.

Upvotes: 0

Murat Çorlu
Murat Çorlu

Reputation: 8545

UPDATE 8 YEARS LATER:

req.path was already doing exactly same thing that I mentioned here. I don't remember how this answer solved issue and accepted as a correct answer but currently it's not a valid answer. Please ignore this answer. Thanks @mhodges for mentioning this.

Original answer:

If you want to really get only "path" without querystring, you can use url library to parse and get only path part of url.

var url = require('url');

//auth required or redirect
app.use('/account', function(req, res, next) {
    var path = url.parse(req.url).pathname;
    if ( !req.session.user ) {
      res.redirect('/login?ref='+path);
    } else {
      next();
    }
});

Upvotes: 16

c1moore
c1moore

Reputation: 1867

For version 4.x you can now use the req.baseUrl in addition to req.path to get the full path. For example, the OP would now do something like:

//auth required or redirect
app.use('/account', function(req, res, next) {
  console.log(req.baseUrl + req.path);  // => /account

  if(!req.session.user) {
    res.redirect('/login?ref=' + encodeURIComponent(req.baseUrl + req.path));  // => /login?ref=%2Faccount
  } else {
    next();
  }
});

Upvotes: 11

Stijn de Witt
Stijn de Witt

Reputation: 42075

//auth required or redirect
app.use('/account', function(req, res, next) {
  console.log(req.path);
  if ( !req.session.user ) {
    res.redirect('/login?ref='+req.path);
  } else {
    next();
  }
});

req.path is / when it should be /account ??

The reason for this is that Express subtracts the path your handler function is mounted on, which is '/account' in this case.

Why do they do this?

Because it makes it easier to reuse the handler function. You can make a handler function that does different things for req.path === '/' and req.path === '/goodbye' for example:

function sendGreeting(req, res, next) {
  res.send(req.path == '/goodbye' ? 'Farewell!' : 'Hello there!')
}

Then you can mount it to multiple endpoints:

app.use('/world', sendGreeting)
app.use('/aliens', sendGreeting)

Giving:

/world           ==>  Hello there!
/world/goodbye   ==>  Farewell!
/aliens          ==>  Hello there!
/aliens/goodbye  ==>  Farewell!

Upvotes: 13

Bahman.A
Bahman.A

Reputation: 1296

req.route.path is working for me

var pool = require('../db');

module.exports.get_plants = function(req, res) {
    // to run a query we can acquire a client from the pool,
    // run a query on the client, and then return the client to the pool
    pool.connect(function(err, client, done) {
        if (err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT * FROM plants', function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            if (err) {
                return console.error('error running query', err);
            }
            console.log('A call to route: %s', req.route.path + '\nRequest type: ' + req.method.toLowerCase());
            res.json(result);
        });
    });
};

after executing I see the following in the console and I get perfect result in my browser.

Express server listening on port 3000 in development mode
A call to route: /plants
Request type: get

Upvotes: 6

Menztrual
Menztrual

Reputation: 41597

After having a bit of a play myself, you should use:

console.log(req.originalUrl)

Upvotes: 343

DivZero
DivZero

Reputation: 2438

In some cases you should use:

req.path

This gives you the path, instead of the complete requested URL. For example, if you are only interested in which page the user requested and not all kinds of parameters the url:

/myurl.htm?allkinds&ofparameters=true

req.path will give you:

/myurl.html

Upvotes: 83

Jürgen Paul
Jürgen Paul

Reputation: 15007

It should be:

req.url

express 3.1.x

Upvotes: 12

Related Questions