如何在Express中获取完整的URL?

Chr*_*ams 441 url node.js express

假设我的样本网址是

http://example.com/one/two

我说我有以下路线

app.get('/one/two', function (req, res) {
    var url = req.url;
}
Run Code Online (Sandbox Code Playgroud)

价值url将是/one/two.

如何在Express中获取完整的URL?例如,在上面的情况下,我想收到http://example.com/one/two.

Pet*_*ons 678

  1. 该协议可用作req.protocol.这里的文档

    1. 在表达3.0之前,您可以假定的协议http除非您看到req.get('X-Forwarded-Protocol')已设置且具有值https,在这种情况下您知道这是您的协议
  2. 主持人来自req.get('host')Gopal指出

  3. 希望您的URL中不需要非标准端口,但如果您确实需要了解它,那么您将在应用程序状态中拥有它,因为它是您app.listen在服务器启动时传递给的任何内容.但是,在非标准端口上进行本地开发的情况下,Chrome似乎在主机头中包含端口,因此req.get('host')返回localhost:3000.因此,至少对于标准端口上的生产站点并直接浏览到您的快速应用程序(没有反向代理)的情况,host标题似乎对URL中的端口做了正确的事情.

  4. 路径来自req.originalUrl(感谢@pgrassant).请注意,此DOES包含查询字符串.这里有关于req.url和req.originalUrl的文档.根据您打算对URL执行的操作,与之originalUrl相比,可能是也可能不是正确的值req.url.

将这些组合在一起以重建绝对URL.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Run Code Online (Sandbox Code Playgroud)

  • 或者使用`req.get('Host')`而不是`req.host`,它给出了主机和端口部分. (56认同)
  • 请求标头中的`host`参数可以被欺骗.如果以这种方式使用`res.host`,可能存在"主机头攻击".在Django框架中,他们有一个'allowed hosts'变量,用于防止此类攻击.我使用的配置变量是我的`root_url`,它可以添加到`req.url`中以便完成.关于攻击:http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html (17认同)
  • -vote:应该使用originalUrl而不是req.url (8认同)
  • @dave客户端可以发送它想要的任何头文件(以及任何URL,端口,随机的非HTTP垃圾),但是,在某些时候,虚假或不准确的头部只会导致协议失败.例如,在虚拟主机环境中,不正确的"主机"标头将显示完全不同的网站.在X-Forwarded-Protocol的情况下,通常不是由实际客户端(浏览器)发送,而是由在应用程序前面提供HTTPS的反向代理(nginx/varnish/apache/whatever)发送. (3认同)
  • 如果您想添加不带参数的 `req.originalUrl`,只需执行 `req.originalUrl.split("?").shift()`。来源:/sf/answers/2248317291/ (2认同)
  • Express 4.x 从 `req.host`、`req.hostname` 和 `req.get('host')` 中剥离端口。未记录但有效的方法是直接访问“req.headers.host”。 (2认同)

Mic*_*bel 115

您可以使用node.js API来表示URLURL.format()从express 传递信息,而不是自己将事物连接在一起.

例:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 在我的例子中,`req.get('host')`只返回*hostname*部分,而不是端口.不知道为什么,但现在我从设置中收集端口号,并使用`hostname`字段,而不是`host`. (4认同)
  • 这不适用于具有查询字符串的 URL。 (4认同)
  • `url.format` 现已弃用。 (4认同)

Nis*_*hah 49

2022年

上面的答案工作正常,但不是文档的首选,因为url.parse现在是这样legacynew URL()所以如果您想更好地控制url.

高速公路

您可以Full URL从下面的代码中获取。

`${req.protocol}://${req.get('host')}${req.originalUrl}`
Run Code Online (Sandbox Code Playgroud)

示例 URL:http://localhost:5000/a/b/c?d=true&e=true#f=false

固定属性(您将在所有路线中获得相同的结果)

`${req.protocol}://${req.get('host')}${req.originalUrl}`
Run Code Online (Sandbox Code Playgroud)

不固定的属性(每条路线都会改变,因为它是由快递本身控制的)

路线:/

req.baseUrl: <blank>
req.url: /a/b/c?d=true&e=true
req.path: /a/b/c
Run Code Online (Sandbox Code Playgroud)

路线/a

req.baseUrl: /a
req.url: /b/c?d=true&e=true
req.path: /b/c
Run Code Online (Sandbox Code Playgroud)

文档: http: //expressjs.com/en/api.html#req.baseUrl

URL封装方式

在该URL函数中,您将在每条路线中获得相同的结果,因此属性始终是固定的

特性

在此输入图像描述

req.protocol: http
req.hostname: localhost
req.get('Host'): localhost:5000
req.originalUrl: /a/b/c?d=true&e=true
req.query: { d: 'true', e: 'true' }
Run Code Online (Sandbox Code Playgroud)

您将得到如下结果。我根据图像更改了属性的顺序,以便它可以匹配图像流。

URL {
  href: 'http://localhost:5000/a/b/c?d=true&e=true',
  protocol: 'http:',
  username: '',
  password: '',
  hostname: 'localhost',
  port: '5000',
  host: 'localhost:5000',
  origin: 'http://localhost:5000',
  pathname: '/a/b/c',
  search: '?d=true&e=true',
  searchParams: URLSearchParams { 'd' => 'true', 'e' => 'true' },
  hash: ''
}
Run Code Online (Sandbox Code Playgroud)

注意Hash无法发送到服务器,因为它像Fragment在服务器中一样处理,但您会在客户端手段浏览器中得到它。

文档: https: //nodejs.org/api/url.html#url_new_url_input_base

  • `get()` 用于获取请求的标头,在请求中,您有 `host` 标头,因此它只需调用请求标头并获取端口,使用起来非常安全,这里没有任何弃用 (2认同)

cho*_*ovy 35

我发现它有点像PITA来获取请求的URL.我不敢相信快递没有更简单的方法.应该是req.requested_url

但这是我如何设置它:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
Run Code Online (Sandbox Code Playgroud)

  • 是否存在`req.port`?它不在Express文档中? (4认同)

mpo*_*lci 17

使用url.format:

var url = require('url');
Run Code Online (Sandbox Code Playgroud)

这支持所有协议并包括端口号.如果您的originalUrl中没有查询字符串,则可以使用此更干净的解决方案:

var requrl = url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl,
});
Run Code Online (Sandbox Code Playgroud)

如果您有查询字符串:

var urlobj = url.parse(req.originalUrl);
urlobj.protocol = req.protocol;
urlobj.host = req.get('host');
var requrl = url.format(urlobj);
Run Code Online (Sandbox Code Playgroud)


los*_*ion 15

这是添加可以在req对象上调用以获取url的函数的好方法

  app.use(function(req, res, next) {
    req.getUrl = function() {
      return req.protocol + "://" + req.get('host') + req.originalUrl;
    }
    return next();
  });
Run Code Online (Sandbox Code Playgroud)

现在您有一个功能,您可以根据需要随时拨打电话.

  • 这不包括用户:密码,你可以在一个完整的URL中获取'http:// user:pass@host.com:8080/p/a/t/h?query = string #hash' (2认同)

小智 11

您可以从express的req中获取完整的url。

function fetchPages(req, res, next) {

    let fullUrl = req.headers.host + req.originalUrl;
    console.log("full url ==> ",fullUrl);
}
Run Code Online (Sandbox Code Playgroud)

  • 这也适用于 nuxtjs! (2认同)

Vag*_*nak 10

用这个,

var url = req.headers.host + '/' + req.url;
Run Code Online (Sandbox Code Playgroud)

  • 使用 var url = req.headers.host + req.url (3认同)

小智 10

使req.host/req.hostname有效必须有两个条件当Express后面的代理:

  1. app.set('trust proxy', 'loopback'); 在app.js
  2. X-Forwarded-Host标头必须由您在Web服务器中指定.例如.apache,nginx

nginx:

server {
    listen myhost:80;
    server_name  myhost;
    location / {
        root /path/to/myapp/public;
        proxy_set_header X-Forwarded-Host $host:$server_port;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://myapp:8080;
    }
}
Run Code Online (Sandbox Code Playgroud)

阿帕奇:

<VirtualHost myhost:80>
    ServerName myhost
    DocumentRoot /path/to/myapp/public
    ProxyPass / http://myapp:8080/
    ProxyPassReverse / http://myapp:8080/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

  • 是的,没有人说过,如果你在 apache 或 nginx 中没有正确的配置,你会从 `req.get('host')` 得到 `127.0.0.1` (2认同)

Edy*_*ura 9

只是下面的代码对我来说就足够了!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Run Code Online (Sandbox Code Playgroud)


mli*_*bre 7

var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;
Run Code Online (Sandbox Code Playgroud)

要么

var full_address = req.protocol + "://" + req.headers.host + req.baseUrl;
Run Code Online (Sandbox Code Playgroud)


Jac*_*cob 7

您可以组合req.protocolreq.hostnamereq.originalUrl。注意req.hostname而不是req.hostor ,req.get("host")它有效但更难阅读。

const completeUrl = `${req.protocol}://${req.hostname}${req.originalUrl}`;
Run Code Online (Sandbox Code Playgroud)


g13*_*13n 6

你需要使用它来构建它req.headers.host + req.url.当然,如果你在不同的端口托管,这样你就会得到这个想法;-)

  • 除了协议之外,这让我得到了一切……有什么可以告诉我的吗? (2认同)

小智 6

我的代码看起来像这样,

params['host_url'] = req.protocol + '://' + req.headers.host + req.url;


Amb*_*xon 6

我建议使用originalUrl而不是URL:

var url = req.protocol + '://' + req.get('host') + req.originalUrl;
Run Code Online (Sandbox Code Playgroud)

请在此处查看originalUrl的说明:http: //expressjs.com/api.html#req.originalUrl

在我们的系统中,我们做了类似的事情,因此originalUrl对我们很重要:

  foo = express();
  express().use('/foo', foo);
  foo.use(require('/foo/blah_controller'));
Run Code Online (Sandbox Code Playgroud)

blah_controller看起来像这样:

  controller = express();
  module.exports = controller;
  controller.get('/bar/:barparam', function(req, res) { /* handler code */ });
Run Code Online (Sandbox Code Playgroud)

所以我们的网址格式如下:

www.example.com/foo/bar/:barparam
Run Code Online (Sandbox Code Playgroud)

因此,我们需要bar控制器获取处理程序中的req.originalUrl.


小智 6

您可以像这样在路线中使用此功能

app.get('/one/two', function (req, res) {
    const url = getFullUrl(req);
}

/**
 * Gets the self full URL from the request
 * 
 * @param {object} req Request
 * @returns {string} URL
 */
const getFullUrl = (req) => `${req.protocol}://${req.headers.host}${req.originalUrl}`;
Run Code Online (Sandbox Code Playgroud)

req.protocol会给你 http 或 https, req.headers.host会给你完整的主机名,比如 www.google.com, req.originalUrl会给pathName你剩下的(在你的情况下/one/two


小智 5

我使用节点包“ url”(npm install url)

它的作用是当您打电话时

url.parse(req.url, true, true)
Run Code Online (Sandbox Code Playgroud)

它将使您能够检索全部或部分网址。更多信息在这里:https : //github.com/defunctzombie/node-url

我以以下方式使用它来获取http://www.example.com/中 /之后的所有内容,以用作变量并提取特定的配置文件(有点像facebook:http://www.facebook。 com / username

    var url = require('url');
    var urlParts = url.parse(req.url, true, true);
    var pathname = urlParts.pathname;
    var username = pathname.slice(1);
Run Code Online (Sandbox Code Playgroud)

尽管要执行此操作,但必须在server.js文件中以这种方式创建路由:

self.routes['/:username'] = require('./routes/users');
Run Code Online (Sandbox Code Playgroud)

并以此方式设置您的路由文件:

router.get('/:username', function(req, res) {
 //here comes the url parsing code
}
Run Code Online (Sandbox Code Playgroud)