如何使用Express Req对象获取请求路径


158

我正在使用express + node.js,并且我有一个req对象,浏览器中的请求是/ account,但是当我登录req.path时,我得到的是'/'---不是'/ 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是/何时应该是/ account?


2
TypeError: Cannot read property 'path' of undefined
chovy 2012年

req.route.path是正确的,并在此处记录。您正在使用哪个版本的Express?
zemirco's

我有同样的问题。req.route未定义。我正在使用快递3.4.4。什么会导致路由不确定?
davidpfahler 2013年

@vinayr req.route.path仍然给我/ create而不是/ quizzes / create,这是整个URL
Sandip Subedi 17-4-15

这是预期的行为。而且您应该拥抱它。您的处理程序不应该关心完整路径,而只关心路径的“本地”部分。那是安装路径之后的部分。这使处理程序功能在其他上下文中更易于重用。
Stijn de Witt

Answers:


234

在自己玩了一点之后,您应该使用:

console.log(req.originalUrl)


3
我认为它与中间件的位置有关,但是您是正确的,这没有任何意义。
Menztrual 2012年

1
绝对是中间件。Express 4中的其他路由器也会发生这种情况。当任何一个安装在给定路径之外时,它内部就会假装它不在根目录下。隔离很不错,但是当您不知道如何获得原始完整价值时会很棘手。感谢您发布!
juanpaco 2015年

3
任何在4.0上使用此工具的人,req.url都被设计成可由中间件可变以用于重新路由,并且req.path可能会丢失挂载点,具体取决于调用的位置。expressjs.com/en/api.html#req.originalUrl
Christian Davis

3
如果您不希望包含查询字符串:const path = req.originalUrl.replace(/\?.*$/, '');
Adam Reis,

1
警告:基于OP问题,这是一个令人误解的答案。如果存在查询字符串,它还将返回查询字符串(例如?a = b&c = 5)。请参阅expressjs.com/en/api.html#req.originalUrl
Ciabaros,

60

在某些情况下,您应该使用:

req.path

这为您提供了路径,而不是完整的请求URL。例如,如果您只对用户请求的页面感兴趣,而不对URL的所有参数感兴趣:

/myurl.htm?allkinds&ofparameters=true

req.path将为您提供:

/myurl.html

1
请注意,如果您要对此URL进行检查,并且在应用程序中有效,则还要包括对斜杠的检查。(即检查/demo也应潜在地进行检查/demo/)。
Vinay,2016年

如果您不希望包含查询字符串:const path = req.originalUrl.replace(/\?.*$/,'');
亚当·里斯

req.path是的简写,url.parse(req.url).pathname应该是被接受的答案
sertsedat

1
@sertsedat不正确。req.path提供您安装应用程序的相对路径。如果将其安装在根目录上,则这是正确的,但是对于/my/path在处安装的应用程序中的路径/myreq.url将给出/path
Stijn de Witt

21

作为补充,这是从文档扩展的示例,该示例很好地包装了您需要在所有情况下使用express来访问路径/ URL的所有知识:

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()
})

基于:https : //expressjs.com/en/api.html#req.originalUrl

结论:如上面c1moore的回答所述,请使用:

var fullPath = req.baseUrl + req.path;


9
//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是/何时应该是/ account?

这样做的原因是Express减去了处理程序函数的安装路径,'/account'在这种情况下就是这样。

他们为什么这样做呢?

因为这样可以更轻松地重用处理程序函数。您可以使处理程序函数执行以下操作req.path === '/'req.path === '/goodbye'例如:

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

然后,您可以将其安装到多个端点:

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

给予:

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

9

如果您想只获取没有查询字符串的“路径”,则可以使用url库来解析并仅获取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();
    }
});

这正是我想要的。req.query.ref如果登录成功,则将其与
Ryan Wu

这很好地工作与通用的代码,因为它符合位置规范。需要记住的事情更少,并且更容易在客户端和服务器之间进行单元测试。
cchamberlain

req.path只是–的别名url.parse(req.url).pathname
mhodges

8

对于4.x版,您现在可以使用req.baseUrlreq.path来获取完整路径。例如,OP现在将执行以下操作:

//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();
  }
});

5

req.route.path为我工作

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);
        });
    });
};

执行后,我在控制台中看到以下内容,并且在浏览器中得到了完美的结果。

Express server listening on port 3000 in development mode
A call to route: /plants
Request type: get
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.