¿Cómo obtener la url completa en Express?

487

Digamos que mi URL de muestra es

http://example.com/one/two

y digo que tengo la siguiente ruta

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

El valor de urlserá /one/two.

¿Cómo obtengo la URL completa en Express? Por ejemplo, en el caso anterior, me gustaría recibir http://example.com/one/two.

Chris Abrams
fuente
66
Para su información, puede inspeccionar el objeto de solicitud y mirar, pero soy un hipócrita y lo encontré aquí.
Jason Sebring

Respuestas:

742
  1. El protocolo está disponible como req.protocol. documentos aquí

    1. Antes de express 3.0, el protocolo que puede suponer ser a httpmenos que vea que req.get('X-Forwarded-Protocol')está configurado y tiene el valor https, en cuyo caso sabe que ese es su protocolo
  2. El host proviene de lo req.get('host')que Gopal ha indicado

  3. Espero que no necesite un puerto no estándar en sus URL, pero si necesita saberlo, lo tendrá en el estado de su aplicación porque es lo que haya pasado al app.listenmomento del inicio del servidor. Sin embargo, en el caso del desarrollo local en un puerto no estándar, Chrome parece incluir el puerto en el encabezado del host , por lo que req.get('host')devuelve localhost:3000, por ejemplo. Entonces, al menos para los casos de un sitio de producción en un puerto estándar y navegando directamente a su aplicación express (sin proxy inverso), el hostencabezado parece hacer lo correcto con respecto al puerto en la URL.

  4. El camino viene de req.originalUrl(gracias @pgrassant). Tenga en cuenta que esto INCLUYE la cadena de consulta. documentos aquí en req.url y req.originalUrl . Dependiendo de lo que pretenda hacer con la URL, originalUrlpuede o no ser el valor correcto en comparación con req.url.

Combina todos esos elementos para reconstruir la URL absoluta.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Peter Lyons
fuente
3
@dave un cliente puede enviar cualquier encabezado que desee (así como cualquier URL, puerto, basura aleatoria que no sea HTTP), sin embargo, en algún momento los encabezados falsos o inexactos simplemente harán que el protocolo falle. Por ejemplo, en un entorno de host virtual, un encabezado "host" incorrecto mostrará un sitio web completamente diferente. En el caso del Protocolo X-Reenviado, eso generalmente no lo envía el cliente real (navegador) sino el proxy inverso (nginx / varnish / apache / lo que sea) que está sirviendo HTTPS frente a su aplicación.
Peter Lyons
59
O use en req.get('Host')lugar de lo req.hostque le da al host más la sección del puerto.
diosney
1
Probablemente sea mejor publicar una pregunta separada para eso. Esta pregunta es sobre express.
Peter Lyons
18
El hostparámetro en los encabezados de solicitud se puede suplantar. Hay un posible "ataque de encabezado de host" si se usa de res.hostesta manera. En el marco de Django, tienen una variable de "hosts permitidos" que se utiliza para prevenir dicho ataque. Yo uso una variable de configuración que es mi root_urlque se puede agregar a la req.urlfinalización. Sobre el ataque: skeletonscribe.net/2013/05/…
Amir Eldor
1
Si desea agregar req.originalUrlsin parámetros, simplemente hágalo req.originalUrl.split("?").shift(). Fuente: stackoverflow.com/a/32118818/2037431
Marcos Pereira
131

En lugar de concatenar las cosas por su cuenta, podría usar la API de node.js para URL y pasar URL.format()la información de express.

Ejemplo:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}
Michael Weibel
fuente
44
En mi caso, req.get('host')solo devuelve la parte del nombre de host , no el puerto. No sé por qué, pero ahora obtengo el número de puerto de la configuración y uso el hostnamecampo en lugar de host.
maxkoryukov
1
En lugar de pathname, creo que te refieres path. Que incluye búsqueda / cadena de consulta
Félix Sanz
3
Esto no funciona para las URL que tienen una cadena de consulta.
Keith
37

Me pareció un poco PITA obtener la URL solicitada. No puedo creer que no haya una manera más fácil de expresar. Debería ser solo req.requested_url

Pero así es como lo configuro:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
chovy
fuente
puerto variable tiene que ser definido?
Amol M Kulkarni
44
¿Existe req.port? ¿No está en la documentación Express?
Mitar
Culpa mía. Supuse que sabrías de qué puerto estás sirviendo y configuré eso antes. Actualizaré el ejemplo nuevamente. También puedes conseguirloreq.app.settings.port
chovy
cuando req.protocol está vacío, ¿significa http?
Codebeat
Este no incluye la consulta. No esta completo. La respuesta aceptada es mejor.
Kostanos
17

Usando url.format :

var url = require('url');

Esto admite todos los protocolos e incluye el número de puerto. Si no tiene una cadena de consulta en su URL original, puede usar esta solución más limpia:

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

Si tiene una cadena de consulta:

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

Aquí hay una excelente manera de agregar una función que puede invocar en el objeto req para obtener la URL

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

Ahora tiene una función a la que puede llamar bajo demanda si la necesita.

perdido en la traducción
fuente
2
Esto no incluye el usuario: contraseña que puede obtener en una url completa ' usuario: [email protected]: 8080 / p / a / t / h? Query = string # hash '
Código exclusivo
@CodeUniquely cierto, pero dado que esa convención ha quedado en desuso durante más de una década, con suerte nadie está realmente incorporando especificaciones de información de usuario en sus API
Mike
11

hacer que req.host/req.hostname sea efectivo debe tener dos condiciones cuando Express detrás de proxies :

  1. app.set('trust proxy', 'loopback'); en app.js
  2. X-Forwarded-HostEl encabezado debe ser especificado por usted en el servidor web. p.ej. 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
fuente
1
sí, nadie dijo eso, si no tienes la configuración correcta en apache o nginx, obtendrás 127.0.0.1dereq.get('host')
Spark.Bao
10

Utilizar este,

var url = req.headers.host + '/' + req.url;
Vaghani Janak
fuente
1
Use var url = req.headers.host + req.url
Sanjeev Kumar el
7
var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;

o

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

Necesitas construirlo usando req.headers.host + req.url. Por supuesto, si está alojado en un puerto diferente y de este modo se le ocurre la idea ;-)

g13n
fuente
1
Eso me da todo menos el protocolo ... ¿hay algo que pueda decirme eso?
Chris Abrams
Para obtener el uso del protocolo:req.protocol
mrded
6

Sugeriría usar originalUrl en lugar de URL:

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

Vea la descripción de originalUrl aquí: http://expressjs.com/api.html#req.originalUrl

En nuestro sistema, hacemos algo como esto, por lo que originalUrl es importante para nosotros:

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

blah_controller se ve así:

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

Entonces nuestras URL tienen el formato:

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

Por lo tanto, necesitamos req.originalUrl en el controlador de barra get get.

Amber Haq Dixon
fuente
6

Mi código se ve así,

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

soomtong
fuente
5

Yo uso el paquete de nodos 'url' (npm install url)

Lo que hace es cuando llamas

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

le dará la posibilidad de recuperar todas o partes de la url. Más información aquí: https://github.com/defunctzombie/node-url

Lo utilicé de la siguiente manera para obtener lo que viene después de / en http://www.example.com/ para usarlo como una variable y extraer un perfil en particular (algo así como 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);

Aunque para que esto funcione, debe crear su ruta de esta manera en su archivo server.js:

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

Y configure su archivo de ruta de esta manera:

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

Puedes usar esta función en la ruta como esta

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.protocolle dará http o https, req.headers.hostle dará el nombre completo del host como www.google.com, req.originalUrlle dará el resto pathName(en su caso /one/two)

Awais Ayub
fuente
¿Podría explicar cómo funciona esta solución? Evite publicar solo respuestas de código en Stack Overflow.
Arcath
@Arcath elaborado.
Awais Ayub
1

Gracias a todos por esta información. Esto es increíblemente molesto.

Agregue esto a su código y nunca tendrá que pensarlo nuevamente:

var app = express();

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

También puede hacer o configurar otras cosas allí, como iniciar sesión en la consola.

Nico
fuente
1

¡Solo el código a continuación fue suficiente para mí!

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