Як отримати повний URL в Express?


486

Скажімо, мій 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
FYI, ви можете оглянути об’єкт запиту і переглянути його, але я лицемір і знайшов його тут.
Джейсон Себрінг

Відповіді:


742
  1. Протокол доступний як req.protocol. Документи тут

    1. Перед Express 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 / лаком / apache / будь-яким іншим), який обслуговує HTTPS перед вашою програмою.
Пітер Ліонс

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

1
Напевно, найкраще опублікувати окреме питання для цього. Це питання стосується експресу.
Пітер Ліонс

18
hostПараметр в заголовках запиту може бути підроблений. При використанні res.hostцього способу можлива "атака заголовка хоста" . У рамках Джанго вони мають змінну "дозволені хости", яка використовується для запобігання такої атаки. Я використовую мою змінну конфігурації, 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()інформацію з експресу.

Приклад:

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.
maxkoryukov

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існує? Це не в документації Експрес?
Мітар

Моє ліжко. Я припускав, що ви знатимете, з якого порту ви обслуговуєте, і встановите це попередньо. Я знову оновлю приклад. Ви також можете отримати йогоreq.app.settings.port
chovy

коли req.protocol порожній, це означає http?
Codebeat

Цей запит не включає запит. Вона не є повною. Прийнята відповідь краще.
Костанос

17

Використання url.format :

var url = require('url');

Ця підтримка підтримує всі протоколи та включає номер порту. Якщо ви не маєте рядок запиту у своєму оригінальномуUrl, ви можете скористатися цим способом очищення:

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
Це не включає користувача: пароль, який ви можете отримати в повному обсязі URL-адреса ' user: pass@host.com: 8080 / p / a / t / h? Query = string # hash '
Код однозначно

@CodeUniquely правда, але оскільки ця конвенція була присуджена вже більше десятиліття, сподіваємось, ніхто фактично не створює специфікації для користувачів у свої 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;
    }
}

апаш :

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


1
так, ніхто не сказав, що якщо у вас немає правильної конфігурації в апачі або 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
грудня 1717

6

Я б запропонував використовувати originalUrl замість URL-адреси:

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

Ознайомтесь з описом originalUrl тут: http://expressjs.com/api.html#req.originalUrl

У нашій системі ми робимо щось подібне, тому для нас важливий оригінальнийUrl:

  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 в панелі контролера отримати обробник.


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 / ім'я користувача )

    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
}

2

Ви можете використовувати цю функцію у такому маршруті

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)


Не могли б ви детальніше розповісти, як працює це рішення. Уникайте публікації відповідей лише на код переповнення стека.
Аркат

@Arcath розроблено.
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()
})

Ви також можете робити або встановлювати інші речі, наприклад, журнал до консолі.


0

Просто коду нижче мені було достатньо!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.