Как получить полный URL в Express?


487

Допустим, мой пример URL

http://example.com/one/two

и я говорю, у меня есть следующий маршрут

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

Значение urlбудет /one/two.

Как получить полный URL-адрес в Express? Например, в случае выше, я хотел бы получить http://example.com/one/two.


6
К вашему сведению, вы можете проверить объект запроса и просмотреть его, но я лицемер и нашел его здесь.
Джейсон Себринг

Ответы:


742
  1. Протокол доступен как req.protocol. документы здесь

    1. До экспресс 3.0, протокол, который вы можете считать, httpесли вы не видите, что req.get('X-Forwarded-Protocol')установлен и имеет значение https, и в этом случае вы знаете, что это ваш протокол
  2. Хозяин пришел, req.get('host')как указал Гопал

  3. Надеюсь, вам не нужен нестандартный порт в ваших URL-адресах, но если вам нужно знать его, вы получите его в состоянии приложения, потому что это то, что вы передали app.listenво время запуска сервера. Тем не менее, в случае локальной разработки на нестандартном порту, Chrome, кажется, включает порт в заголовок узла, поэтому req.get('host')возвращает localhost:3000, например. Так что, по крайней мере, в случае с рабочим сайтом на стандартном порте и просмотром непосредственно в вашем экспресс-приложении (без обратного прокси-сервера) hostзаголовок, кажется, правильно работает с портом в URL.

  4. Путь исходит от req.originalUrl(спасибо @pgrassant). Обратите внимание, что это включает в себя строку запроса. документы здесь на req.url и req.originalUrl . В зависимости от того, что вы собираетесь делать с URL, originalUrlможет быть или не быть правильное значение по сравнению с req.url.

Объедините все это вместе, чтобы восстановить абсолютный URL.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;

3
@ dave клиент может отправлять любые заголовки, которые он хочет (а также любой URL, порт, случайный не HTTP-мусор), однако в какой-то момент поддельные или неточные заголовки просто вызовут сбой протокола. Например, в среде виртуального хоста неправильный заголовок «хост» будет отображать совершенно другой веб-сайт. В случае X-Forwarded-Protocol это обычно отправляется не реальным клиентом (браузером), а обратным прокси-сервером (nginx / varnish / apache / что угодно), который обслуживает HTTPS перед вашим приложением.
Питер Лайонс

59
Или используйте req.get('Host')вместо req.hostкоторого дает хост плюс раздел порта.
Диосней

1
Наверное, лучше всего написать отдельный вопрос для этого. Этот вопрос о экспрессе.
Питер Лайонс

18
hostПараметр в заголовках запроса может быть подделан. При использовании res.hostэтого способа возможна «атака заголовка узла» . В структуре Django у них есть переменная «позволенные хосты», которая используется для предотвращения такой атаки. Я использую конфигурационную переменную, root_urlкоторую я могу добавить к req.urlзавершению. Об атаке: skeletonscribe.net/2013/05/…
Амир Элдор

1
Если вы хотите добавить req.originalUrlбез параметров, просто сделайте req.originalUrl.split("?").shift(). Источник: stackoverflow.com/a/32118818/2037431
Маркос Перейра

131

Вместо того, чтобы объединять все вместе, вы можете использовать API-интерфейс node.js для URL-адресов и передавать URL.format()информацию из Express.

Пример:

var url = require('url');

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

4
В моем случае req.get('host')возвращает только часть имени хоста , а не порт. Не знаю почему, но теперь я собираю номер порта из настроек и использую hostnameполе вместо host.
Макскорюков

1
Вместо pathname, я думаю, вы имеете в виду path. Который включает
Félix Sanz

3
Это не работает для URL, которые имеют строку запроса.
Кит

37

Я нашел немного 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;

переменная порта должна быть определена?
Amol M Kulkarni

4
Существует req.port? Это не в документации Express?
Mitar

Виноват. Я предполагал, что вы будете знать, с какого порта вы обслуживаете, и установил это ранее. Я обновлю пример снова. Вы также можете получить это сreq.app.settings.port
chovy

когда req.protocol пуст, значит ли это http?
Codebeat

Этот не включает в себя запрос. Это не завершено. Принятый ответ лучше.
Костанос

17

Используя url.format :

var url = require('url');

Это поддерживает все протоколы и включает номер порта. Если у вас нет строки запроса в вашем originalUrl, вы можете использовать это более чистое решение:

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

Если у вас есть строка запроса:

var urlobj = url.parse(req.originalUrl);
urlobj.protocol = req.protocol;
urlobj.host = req.get('host');
var requrl = url.format(urlobj);

16

Вот отличный способ добавить функцию, которую вы можете вызвать в объекте req, чтобы получить URL

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

Теперь у вас есть функция, которую вы можете вызвать по требованию, если вам это нужно.


2
Сюда не входит user: пароль, который вы можете получить по полной ссылке ' user: pass@host.com: 8080 / p / a / t / h? Query = string # hash '
уникальный код

@CodeUniquely верно, но так как это соглашение устарело уже более десяти лет, надеюсь, никто на самом деле не встраивает спецификации userinfo в свои API
Майк

11

Для того чтобы сделать req.host/req.hostname эффективным, должно быть два условия, когда Express находится за прокси :

  1. app.set('trust proxy', 'loopback'); в app.js
  2. X-Forwarded-Hostзаголовок должен быть указан вами в веб-сервере. например. 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;
    }
}

apache :

<VirtualHost myhost:80>
    ServerName myhost
    DocumentRoot /path/to/myapp/public
    ProxyPass / http://myapp:8080/
    ProxyPassReverse / http://myapp:8080/
</VirtualHost>


1
да, никто не сказал, что, если у вас нет правильной конфигурации в apache или nginx, вы получите 127.0.0.1отreq.get('host')
Spark.Bao


7
var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;

или

var full_address = req.protocol + "://" + req.headers.host + req.baseUrl;

6

Вы должны построить это, используя req.headers.host + req.url. Конечно, если вы размещаете хостинг в другом порту, вы поймете идею ;-)


1
Это дает мне все, кроме протокола ... есть что-нибудь, что может мне это сказать?
Крис Абрамс

Чтобы получить протокол, используйте:req.protocol
mrded

6

Я бы предложил использовать originalUrl вместо URL:

var url = req.protocol + '://' + req.get('host') + req.originalUrl;

Смотрите описание originalUrl здесь: http://expressjs.com/api.html#req.originalUrl

В нашей системе мы делаем что-то вроде этого, поэтому для нас важен originalUrl:

  foo = express();
  express().use('/foo', foo);
  foo.use(require('/foo/blah_controller'));

blah_controller выглядит так:

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

Таким образом, наши URL имеют формат:

www.example.com/foo/bar/:barparam

Следовательно, нам нужен req.originalUrl в обработчике get контроллера bar.


6

Мой код выглядит так,

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


5

Я использую пакет узла 'url' (npm install url)

Что это делает, когда вы звоните

url.parse(req.url, true, true)

это даст вам возможность получить все или часть URL. Более подробная информация здесь: 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);

Хотя, чтобы это работало, вы должны создать свой маршрут таким образом в вашем файле server.js:

self.routes['/:username'] = require('./routes/users');

И установите свой файл маршрута следующим образом:

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

3

Вы можете использовать эту функцию в маршруте, как это

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

req.protocolдаст вам http или https, req.headers.hostдаст вам полное имя хоста, например www.google.com, req.originalUrlдаст остальное pathName(в вашем случае /one/two)


Не могли бы вы рассказать, как работает это решение? Старайтесь не размещать ответы с кодом только в переполнении стека.
Аркат

@ Аркат разработал.
Awais Ayub

1

Спасибо всем за эту информацию. Это невероятно раздражает.

Добавьте это в свой код, и вам никогда не придется думать об этом снова:

var app = express();

app.all("*", function (req, res, next) {  // runs on ALL requests
    req.fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
        next()
})

Вы также можете делать или устанавливать другие вещи, такие как вход в консоль.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.