Comment obtenir l'URL complète dans Express?

487

Disons que mon exemple d'URL est

http://example.com/one/two

et je dis que j'ai l'itinéraire suivant

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

La valeur de urlsera /one/two.

Comment obtenir l' URL complète dans Express? Par exemple, dans le cas ci-dessus, j'aimerais recevoir http://example.com/one/two.

Chris Abrams
la source
6
Pour info, vous pouvez inspecter l'objet de requête et regarder à travers mais je suis un hypocrite et je l'ai trouvé ici.
Jason Sebring du

Réponses:

742
  1. Le protocole est disponible en req.protocol. docs ici

    1. Avant express 3.0, le protocole que vous pouvez supposer être httpsauf si vous voyez qu'il req.get('X-Forwarded-Protocol')est défini et a la valeur https, auquel cas vous savez que c'est votre protocole
  2. L'hôte vient req.get('host')comme Gopal l'a indiqué

  3. J'espère que vous n'avez pas besoin d'un port non standard dans vos URL, mais si vous aviez besoin de le connaître, vous l'auriez dans l'état de votre application, car c'est tout ce que vous avez transmis app.listenau démarrage du serveur. Cependant, dans le cas d'un développement local sur un port non standard, Chrome semble inclure le port dans l'en-tête de l'hôte donc req.get('host')retourne localhost:3000, par exemple. Donc, au moins pour les cas d'un site de production sur un port standard et naviguant directement vers votre application express (sans proxy inverse), l'en- hosttête semble faire ce qu'il faut concernant le port dans l'URL.

  4. Le chemin vient de req.originalUrl(merci @pgrassant). Notez que cela inclut la chaîne de requête. docs ici sur req.url et req.originalUrl . Selon ce que vous avez l'intention de faire avec l'URL, la valeur originalUrlpeut être ou non correcte par rapport à req.url.

Combinez-les tous ensemble pour reconstruire l'URL absolue.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Peter Lyons
la source
3
@dave, un client peut envoyer les en-têtes qu'il veut (ainsi que l'URL, le port, les déchets non HTTP aléatoires), mais à un moment donné, des en-têtes faux ou inexacts entraîneront simplement l'échec du protocole. Par exemple, dans un environnement d'hôte virtuel, un en-tête «hôte» incorrect affichera un site Web complètement différent. Dans le cas du protocole X-Forwarded, ce n'est généralement pas envoyé par le client réel (navigateur) mais par le proxy inverse (nginx / vernis / apache / autre) qui sert HTTPS devant votre application.
Peter Lyons
59
Ou utilisez req.get('Host')au lieu de req.hostcela donne l'hôte plus la section de port.
diosney
1
Il est probablement préférable de poster une question distincte pour cela. Cette question concerne l'express.
Peter Lyons
18
Le hostparamètre dans les en-têtes de demande peut être usurpé. Il y a une "attaque d'en-tête d'hôte" possible si vous utilisez res.hostcette méthode. Dans le framework Django, ils ont une variable «hôtes autorisés» qui est utilisée pour empêcher une telle attaque. J'utilise une variable de configuration qui est la mienne et root_urlqui peut être ajoutée à la req.urlpour terminer. À propos de l'attaque: skeletonscribe.net/2013/05/…
Amir Eldor
1
Si vous souhaitez ajouter req.originalUrlsans paramètres, faites-le simplement req.originalUrl.split("?").shift(). Source: stackoverflow.com/a/32118818/2037431
Marcos Pereira
131

Au lieu de concaténer les choses ensemble par vous-même, vous pouvez utiliser l'API node.js pour les URL et transmettre URL.format()les informations depuis express.

Exemple:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}
Michael Weibel
la source
4
Dans mon cas, le req.get('host')retourne uniquement la partie du nom d'hôte , pas le port. Je ne sais pas pourquoi, mais maintenant je récupère le numéro de port dans les paramètres et utilise le hostnamechamp à la place de host.
maxkoryukov
1
Au lieu de pathname, je pense que vous voulez dire path. Qui inclut la recherche / recherche de chaînes
Félix Sanz
3
Cela ne fonctionne pas pour les URL qui ont une chaîne de requête.
Keith
37

Je l'ai trouvé un peu PITA pour obtenir l'URL demandée. Je ne peux pas croire qu'il n'y ait pas de moyen plus simple d'exprimer. Devrait simplement être req.requested_url

Mais voici comment je l'ai réglé:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
chovy
la source
variable de port doit être définie?
Amol M Kulkarni
4
req.portExiste- t- il? Ce n'est pas dans la documentation Express?
Mitar
Ma faute. J'ai supposé que vous sauriez de quel port vous servez et que vous l'avez défini avant. Je mettrai à jour l'exemple à nouveau. Vous pouvez également l'obtenir avecreq.app.settings.port
chovy
lorsque req.protocol est vide, cela signifie-t-il http?
Codebeat
Celui-ci n'inclut pas la requête. Ce n'est pas complet. La réponse acceptée est meilleure.
Kostanos
17

Utilisation de url.format :

var url = require('url');

Cela prend en charge tous les protocoles et inclut le numéro de port. Si vous n'avez pas de chaîne de requête dans votre originalUrl, vous pouvez utiliser cette solution de nettoyage:

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

Si vous avez une chaîne de requête:

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

Voici un excellent moyen d'ajouter une fonction que vous pouvez appeler sur l'objet req pour obtenir l'url

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

Vous avez maintenant une fonction que vous pouvez appeler sur demande si vous en avez besoin.

perdu dans la traduction
la source
2
Cela n'inclut pas l'utilisateur: mot de passe que vous pouvez obtenir dans une URL complète ' utilisateur: [email protected]: 8080 / p / a / t / h? Query = string # hash '
Code Uniquely
@CodeUniquement vrai, mais depuis que cette convention est obsolète depuis plus d'une décennie maintenant, j'espère que personne ne construit en fait des spécifications userinfo dans ses API
Mike
11

rendre req.host/req.hostname efficace doit avoir deux conditions lorsque Express derrière des proxys :

  1. app.set('trust proxy', 'loopback'); dans app.js
  2. X-Forwarded-Hostl'en-tête doit être spécifié par vous-même dans le serveur Web. par exemple. 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
la source
1
oui, personne n'a dit que, si vous n'avez pas de configuration correcte dans apache ou nginx, vous obtiendrez 127.0.0.1dereq.get('host')
Spark.Bao
10

Utilisez ceci,

var url = req.headers.host + '/' + req.url;
Vaghani Janak
la source
1
Utilisez var url = req.headers.host + req.url
Sanjeev Kumar
7
var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;

ou

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

Vous devez le construire en utilisant req.headers.host + req.url. Bien sûr, si vous hébergez dans un port différent et que vous avez l'idée ;-)

g13n
la source
1
Cela me donne tout sauf le protocole ... y a-t-il quelque chose qui puisse me dire cela?
Chris Abrams
Pour obtenir le protocole, utilisez:req.protocol
2017
6

Je suggérerais d'utiliser originalUrl au lieu de l'URL:

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

Voir la description de originalUrl ici: http://expressjs.com/api.html#req.originalUrl

Dans notre système, nous faisons quelque chose comme ça, donc originalUrl est important pour nous:

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

blah_controller ressemble à ceci:

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

Nos URL ont donc le format:

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

Par conséquent, nous avons besoin de req.originalUrl dans le gestionnaire get du contrôleur de barre.

Amber Haq Dixon
la source
6

Mon code ressemble à ceci,

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

soomtong
la source
5

J'utilise le package de noeud 'url' (URL d'installation npm)

Ce qu'il fait, c'est lorsque vous appelez

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

il vous donnera la possibilité de récupérer tout ou partie de l'url. Plus d'informations ici: https://github.com/defunctzombie/node-url

Je l'ai utilisé de la manière suivante pour obtenir tout ce qui vient après le / dans http://www.example.com/ pour l'utiliser comme variable et afficher un profil particulier (un peu comme Facebook: http: //www.facebook. com / nom d'utilisateur )

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

Bien que cela fonctionne, vous devez créer votre itinéraire de cette façon dans votre fichier server.js:

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

Et définissez votre fichier d'itinéraire de cette façon:

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

Vous pouvez utiliser cette fonction dans l'itinéraire comme celui-ci

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.protocolvous donnera http ou https, req.headers.hostvous donnera le nom d'hôte complet comme www.google.com, req.originalUrldonnera le restepathName (dans votre cas /one/two)

Awais Ayub
la source
Pourriez-vous nous expliquer comment cette solution fonctionne. Évitez de publier des réponses de code uniquement sur Stack Overflow.
Arcath
@Arcath a élaboré.
Awais Ayub
1

Merci à tous pour ces informations. C'est incroyablement ennuyeux.

Ajoutez ceci à votre code et vous n'aurez plus jamais à y penser:

var app = express();

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

Vous pouvez également faire ou définir d'autres choses, telles que la connexion à la console.

Nico
la source
1

Juste le code ci-dessous me suffisait!

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