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.


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;

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

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;

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);

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.


2
Dies beinhaltet nicht das Benutzer: Passwort, das Sie in einer vollständigen URL erhalten können. ' Benutzer: pass@host.com: 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>


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


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

oder

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

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 ;-)


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.


6

Mein Code sieht so aus,

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


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
}

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)


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.


0

Nur der folgende Code hat mir gereicht!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.