Wie erhalte ich die vollständige URL in Express?

486

Angenommen, meine Beispiel-URL lautet

http://example.com/one/two

und ich sage, ich habe die folgende Route

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

Der Wert von urlwird sein /one/two.

Wie erhalte ich die vollständige URL in Express? Im obigen Fall möchte ich zum Beispiel erhalten http://example.com/one/two.

Chris Abrams
quelle
6
Zu Ihrer Information, Sie können das Anforderungsobjekt inspizieren und durchsehen, aber ich bin ein Heuchler und habe es hier gefunden.
Jason Sebring

Antworten:

742
  1. Das Protokoll ist verfügbar als req.protocol. Dokumente hier

    1. Vor 3.0 auszudrücken, kann das Protokoll Sie davon ausgehen , sein , httpwenn Sie sehen , dass req.get('X-Forwarded-Protocol')festgelegt ist und den Wert https, in welchem Fall Sie wissen , das ist Ihr Protokoll
  2. Der Gastgeber kommt von, req.get('host')wie Gopal angegeben hat

  3. Hoffentlich benötigen Sie keinen nicht standardmäßigen Port in Ihren URLs, aber wenn Sie ihn kennen müssten, hätten Sie ihn in Ihrem Anwendungsstatus, da er app.listenbeim Start des Servers übergeben wurde. Im Fall der lokalen Entwicklung jedoch auf einem Nicht-Standard - Port, scheint Chrome den Port in den Host - Header so enthalten req.get('host')kehrt localhost:3000, zum Beispiel. Zumindest für den Fall, dass sich eine Produktionsstätte an einem Standardport befindet und direkt zu Ihrer Express-App navigiert (ohne Reverse-Proxy), hostscheint der Header in Bezug auf den Port in der URL das Richtige zu tun.

  4. Der Pfad kommt von req.originalUrl(danke @pgrassant). Beachten Sie, dass dies die Abfragezeichenfolge enthält. Dokumente hier auf req.url und req.originalUrl . Abhängig davon, was Sie mit der URL tun möchten, originalUrlkann dies im Vergleich zu der richtige Wert sein oder auch nicht req.url.

Kombinieren Sie diese alle zusammen, um die absolute URL zu rekonstruieren.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Peter Lyons
quelle
3
@dave Ein Client kann beliebige Header senden (sowie URL, Port, zufälligen Nicht-HTTP-Müll). Irgendwann führen jedoch falsche oder ungenaue Header einfach zum Fehlschlagen des Protokolls. In einer virtuellen Hostumgebung zeigt beispielsweise ein falscher "Host" -Header eine völlig andere Website an. Im Fall von X-Forwarded-Protocol wird dies normalerweise nicht vom eigentlichen Client (Browser) gesendet, sondern vom Reverse-Proxy (Nginx / Lack / Apache / was auch immer), der HTTPS vor Ihrer Anwendung bereitstellt.
Peter Lyons
59
Oder verwenden Sie req.get('Host')stattdessen req.hostden Host plus den Portabschnitt.
Diosney
1
Wahrscheinlich am besten eine separate Frage dazu posten. Bei dieser Frage geht es um Express.
Peter Lyons
18
Der hostParameter in den Anforderungsheadern kann gefälscht werden. Es gibt einen möglichen "Host-Header-Angriff", wenn Sie res.hostdiese Methode verwenden. Im Django-Framework verfügen sie über eine Variable "Zulässige Hosts", mit der ein solcher Angriff verhindert wird. Ich verwende eine Konfigurationsvariable, die mir zur Vervollständigung root_urlhinzugefügt werden kann req.url. Über den Angriff: skeletonscribe.net/2013/05/…
Amir Eldor
1
Wenn Sie req.originalUrlohne Parameter hinzufügen möchten , tun Sie dies einfach req.originalUrl.split("?").shift(). Quelle: stackoverflow.com/a/32118818/2037431
Marcos Pereira
131

Anstatt die Dinge selbst zu verketten, können Sie stattdessen die node.js-API für URLs verwenden und URL.format()die Informationen von express übergeben.

Beispiel:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}
Michael Weibel
quelle
4
In meinem Fall req.get('host')gibt der nur den Hostnamen- Teil zurück, nicht den Port. Ich weiß nicht warum, aber jetzt sammle ich die Portnummer aus den Einstellungen und verwende hostnamestattdessen das Feld host.
Maxkoryukov
1
Stattdessen pathnamemeine ich, du meinst path. Welches beinhaltet Suche / Querystring
Félix Sanz
3
Dies funktioniert nicht für URLs mit einer Abfragezeichenfolge.
Keith
37

Ich fand es ein bisschen wie eine PITA, die angeforderte URL zu bekommen. Ich kann nicht glauben, dass es keinen einfacheren Weg im Express gibt. Sollte nur req.requested_url sein

Aber so stelle ich es ein:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
chovy
quelle
Portvariable muss definiert werden?
Amol M Kulkarni
4
Existiert req.port? Es ist nicht in der Express-Dokumentation?
Mitar
Mein Fehler. Ich nahm an, Sie würden wissen, von welchem ​​Port aus Sie bedienen, und dies vorher festlegen. Ich werde das Beispiel erneut aktualisieren. Sie können es auch mitreq.app.settings.port
chovy
Wenn req.protocol leer ist, bedeutet das http?
Codebeat
Dieser enthält die Abfrage nicht. Es ist nicht vollständig. Die akzeptierte Antwort ist besser.
Kostanos
17

Verwenden von url.format :

var url = require('url');

Dies unterstützt alle Protokolle und enthält die Portnummer. Wenn Ihre originalUrl keine Abfragezeichenfolge enthält, können Sie diese sauberere Lösung verwenden:

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

Wenn Sie eine Abfragezeichenfolge haben:

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

Hier ist eine großartige Möglichkeit, eine Funktion hinzuzufügen, die Sie für das req-Objekt aufrufen können, um die URL abzurufen

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

Jetzt haben Sie eine Funktion, die Sie bei Bedarf aufrufen können.

verlorene Übersetzung
quelle
2
Dies beinhaltet nicht das Benutzer: Passwort, das Sie in einer vollständigen URL erhalten können. ' Benutzer: [email protected]: 8080 / p / a / t / h? Query = string # hash '
Code eindeutig
@CodeUniquely true, aber da diese Konvention seit über einem Jahrzehnt veraltet ist, baut hoffentlich niemand tatsächlich Userinfo-Spezifikationen in seine APIs ein
Mike
11

Damit req.host/req.hostname wirksam wird, müssen zwei Bedingungen erfüllt sein, wenn Express hinter Proxys ausgeführt wird :

  1. app.set('trust proxy', 'loopback'); in app.js.
  2. X-Forwarded-HostDer Header muss von Ihnen im Webserver angegeben werden. z.B. 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>
zhi.yang
quelle
1
Ja, niemand hat gesagt, dass, wenn Sie keine korrekte Konfiguration in Apache oder Nginx haben, Sie 127.0.0.1vonreq.get('host')
Spark.Bao
10

Benutze das,

var url = req.headers.host + '/' + req.url;
Vaghani Janak
quelle
1
Verwenden Sie var url = req.headers.host + req.url
Sanjeev Kumar
7
var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;

oder

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

Sie müssen es mit konstruieren req.headers.host + req.url. Natürlich, wenn Sie in einem anderen Port hosten und so kommen Sie auf die Idee ;-)

g13n
quelle
1
Das bringt mir alles außer dem Protokoll ... gibt es irgendetwas, das mir das sagen kann?
Chris Abrams
Um das Protokoll zu erhalten, verwenden Sie:req.protocol
mrded
6

Ich würde vorschlagen, originalUrl anstelle von URL zu verwenden:

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

Die Beschreibung von originalUrl finden Sie hier: http://expressjs.com/api.html#req.originalUrl

In unserem System machen wir so etwas, daher ist originalUrl für uns wichtig:

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

blah_controller sieht folgendermaßen aus:

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

Unsere URLs haben also das Format:

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

Daher benötigen wir req.originalUrl im Bar-Controller-Get-Handler.

Amber Haq Dixon
quelle
6

Mein Code sieht so aus,

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

Soomtong
quelle
5

Ich benutze das Knotenpaket 'url' (npm install url)

Was es tut, ist, wenn Sie anrufen

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

Es gibt Ihnen die Möglichkeit, die URL ganz oder teilweise abzurufen. Weitere Informationen hier: https://github.com/defunctzombie/node-url

Ich habe es folgendermaßen verwendet, um alles, was nach dem / in http://www.example.com/ kommt , als Variable zu verwenden und ein bestimmtes Profil aufzurufen (ähnlich wie Facebook: http: //www.facebook). com / Benutzername )

    var url = require('url');
    var urlParts = url.parse(req.url, true, true);
    var pathname = urlParts.pathname;
    var username = pathname.slice(1);

Damit dies funktioniert, müssen Sie Ihre Route in der Datei server.js folgendermaßen erstellen:

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

Und stellen Sie Ihre Routendatei folgendermaßen ein:

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

Sie können diese Funktion auf dieser Route verwenden

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.protocolgibt Ihnen http oder https, req.headers.hostgibt Ihnen den vollständigen Hostnamen wie www.google.com, req.originalUrlgibt den Rest pathName(in Ihrem Fall /one/two)

Awais Ayub
quelle
Könnten Sie näher erläutern, wie diese Lösung funktioniert? Vermeiden Sie es, nur Antworten auf den Stapelüberlauf zu veröffentlichen.
Arcath
@Arcath ausgearbeitet.
Awais Ayub
1

Vielen Dank für diese Informationen. Das ist unglaublich nervig.

Fügen Sie dies Ihrem Code hinzu und Sie müssen nie wieder darüber nachdenken:

var app = express();

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

Sie können dort auch andere Dinge tun oder festlegen, z. B. An der Konsole protokollieren.

Nico
quelle
0

Nur der folgende Code hat mir gereicht!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Edy Segura
quelle