【问题标题】:how to get request path with express req object如何使用 express req 对象获取请求路径
【发布时间】:2012-09-13 14:30:41
【问题描述】:

我正在使用 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 ??

【问题讨论】:

  • TypeError: Cannot read property 'path' of undefined
  • req.route.path 是正确的并记录在here。您使用的是哪个版本的 express?
  • 我遇到了同样的问题。 req.route 未定义。我使用快递 3.4.4。什么会导致路由未定义?
  • @vinayr req.route.path 仍然给我 /create 而不是 /quizzes/create,这是整个 URL
  • 这是预期行为。你应该接受它。您的处理程序不应该关心完整路径,而只关心路径的“本地”部分。这是安装路径之后的部分。这使得处理函数更容易在其他上下文中重用。

标签: javascript node.js express


【解决方案1】:

自己玩了一会之后,你应该使用:

console.log(req.originalUrl)

【讨论】:

  • 我认为这与中间件的定位有关,但你是对的,这没有意义。
  • 绝对是中间件。 Express 4 中的其他路由器也会发生这种情况。当任何一个安装在给定路径之外时,它在自身内部就会假装它不在根目录下。这对于隔离来说很好,但是当您不知道如何获得原始完整值时会很棘手。感谢您发布此信息!
  • 任何人在 4.0 上都能看到,req.url 被设计为可以被中间件更改以用于重新路由,并且 req.path 可能会丢失安装点,具体取决于它被调用的位置。 expressjs.com/en/api.html#req.originalUrl
  • 如果您不想包含查询字符串:const path = req.originalUrl.replace(/\?.*$/, '');
  • 警告:这是基于 OP 问题的误导性答案。如果存在,这也将返回查询字符串(例如 ?a=b&c=5)。见expressjs.com/en/api.html#req.originalUrl
【解决方案2】:

在某些情况下你应该使用:

req.path

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

/myurl.htm?allkinds&ofparameters=true

req.path 会给你:

/myurl.html

【讨论】:

  • 请注意,如果您对这个 URL 进行检查,还要检查尾部斜杠是否在您的应用中有效。 (即检查/demo 也应该检查/demo/)。
  • 如果不希望包含查询字符串: const path = req.originalUrl.replace(/\?.*$/, '');
  • req.pathurl.parse(req.url).pathname 的简写,这应该是公认的答案
  • @sertsedat 不正确。 req.path 为您提供安装应用程序的相对路径。如果它安装在根目录下是正确的,但对于路径/my/path,在安装在/my 的应用程序中,req.url 将给出/path
【解决方案3】:

作为补充,这里是从文档扩展而来的示例,它很好地包含了您在所有情况下使用 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's answer 所说,使用:

var fullPath = req.baseUrl + req.path;

【讨论】:

    【解决方案4】:

    8 年后更新:

    req.path 是我在这里提到的already doing exactly same thing。我不记得这个答案是如何解决问题并被接受为正确答案的,但目前这不是一个有效的答案。请忽略这个答案。感谢@mhodges 提到这一点。

    原答案:

    如果你真的想只得到没有查询字符串的“路径”,你可以使用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 一起使用
    • 这适用于通用代码,因为它符合 Location 规范。需要记住的事情更少,并且更容易跨客户端和服务器进行单元测试。
    • req.path 只是 url.parse(req.url).pathname 的别名
    • @mhodges 哇,这看起来完全正确。这是一个已有 8 年历史的答案,我不知道我们认为该答案如何解决了这个问题。谢谢提及。我会更新答案或者干脆删除它。
    【解决方案5】:

    应该是:

    req.url

    表达 3.1.x

    【讨论】:

    【解决方案6】:

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

    【讨论】:

      【解决方案7】:
      //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!
      

      【讨论】:

        【解决方案8】:

        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
        

        【讨论】:

          【解决方案9】:

          1。直接从主文件(app.js / index.js)调用:

          app.get('/admin/:foo/:bar/:baz', async (req, res) => {
              console.log(req.originalUrl);
              console.log(req.url);
              console.log(req.path);
              console.log(req.route.path);
              console.log(req.baseUrl);
              console.log(req.hostname);
              console.log(req.headers.host) // OR req.header('host'));
              console.log(req.protocol);
          
              res.sendStatus(200);
          });
          

          API 调用:

          http://localhost:3000/admin/a/b/c
          

          输出

          /admin/a/b/c (originalUrl)
          /admin/a/b/c (url)
          /admin/a/b/c (path)
          /admin/:foo/:bar/:baz (route.path)
          (baseUrl)
          localhost(主机名)
          localhost:3000(headers.host(主机名和端口号))
          http(协议)


          2。从模块调用:

          app.js

          const express = require('express');
          const app = express();
          
          ...
          
          const users = require('./users');
          app.use('/api/users', users);
          

          users.js

          const express = require('express');
          const router = express.Router();
          
          ...
          
          router.get('/admin/:foo/:bar/:baz', async (req, res) => {
              console.log(req.originalUrl);
              console.log(req.url);
              console.log(req.path);
              console.log(req.route.path);
              console.log(req.baseUrl);
              console.log(req.hostname);
              console.log(req.headers.host) // OR req.header('host'));
              console.log(req.protocol);
          
              res.sendStatus(200);
          });
          

          API 调用:

          http://localhost:3000/admin/a/b/c
          

          输出

          /api/users/admin/a/b/c (originalUrl)
          /admin/a/b/c (url)
          /admin/a/b/c (path)
          /admin/:foo/:bar/:baz (route.path)
          /api/users (baseUrl)
          localhost(主机名)
          localhost:3000(headers.host(主机名和端口号))
          http(协议)

          【讨论】:

          • req.routeundefined
          • 你能分享你的代码 sn-p(例如 JSFiddle 等)吗?
          猜你喜欢
          • 1970-01-01
          • 2018-01-01
          • 2014-01-27
          • 1970-01-01
          • 1970-01-01
          • 2020-07-11
          • 1970-01-01
          • 1970-01-01
          • 2020-06-28
          相关资源
          最近更新 更多