Como obter o URL completo no Express?


486

Digamos que meu URL de amostra seja

http://example.com/one/two

e eu digo que tenho a seguinte rota

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

O valor de urlserá /one/two.

Como obtenho o URL completo no Express? Por exemplo, no caso acima, eu gostaria de receber http://example.com/one/two.


6
Para sua informação, você pode inspecionar o objeto de solicitação e examinar, mas eu sou um hipócrita e o encontrei aqui.
Jason Sebring

Respostas:


742
  1. O protocolo está disponível como req.protocol. docs aqui

    1. Antes do express 3.0, o protocolo que você pode assumir, a httpmenos que você veja que req.get('X-Forwarded-Protocol')está definido e tem o valor https; nesse caso, você sabe que é o seu protocolo
  2. O anfitrião vem req.get('host')como Gopal indicou

  3. Espero que você não precise de uma porta não padrão em seus URLs, mas se você soubesse, você a teria no estado do aplicativo, porque é o que você passou app.listenno momento da inicialização do servidor. No entanto, no caso de desenvolvimento local em uma porta não padrão, o Chrome parece incluir a porta no cabeçalho do host , req.get('host')retornando localhost:3000, por exemplo. Portanto, pelo menos nos casos de um site de produção em uma porta padrão e navegando diretamente para seu aplicativo expresso (sem proxy reverso), o hostcabeçalho parece fazer a coisa certa em relação à porta na URL.

  4. O caminho vem req.originalUrl(obrigado @pgrassant). Observe que isso inclui a string de consulta. docs aqui em req.url e req.originalUrl . Dependendo do que você pretende fazer com o URL, originalUrlpode ou não ser o valor correto em comparação com req.url.

Combine tudo isso para reconstruir o URL absoluto.

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

3
@dave um cliente pode enviar os cabeçalhos que desejar (assim como qualquer URL, porta, lixo aleatório não HTTP), no entanto, em algum momento, cabeçalhos falsos ou imprecisos simplesmente causarão falha no protocolo. Por exemplo, em um ambiente de host virtual, um cabeçalho de "host" incorreto exibirá um site completamente diferente. No caso do X-Forwarded-Protocol, isso geralmente não é enviado pelo cliente real (navegador), mas pelo proxy reverso (nginx / verniz / apache / o que for) que está servindo HTTPS na frente do seu aplicativo.
Peter Lyons

59
Ou use em req.get('Host')vez de req.hostque fornece ao host mais a seção da porta.
diosney

1
Provavelmente, é melhor postar uma pergunta separada para isso. Esta pergunta é sobre expressa.
Peter Lyons

18
O hostparâmetro nos cabeçalhos da solicitação pode ser falsificado. Existe um possível "ataque ao cabeçalho do host" se for usado res.hostdessa maneira. Na estrutura do Django, eles têm uma variável 'hosts permitidos' que é usada para impedir esse ataque. Eu uso uma variável de configuração que é minha, root_urlque pode ser adicionada à req.urlconclusão. Sobre o ataque: skeletonscribe.net/2013/05/…
Amir Eldor

1
Se você deseja adicionar req.originalUrlsem parâmetros, basta fazer req.originalUrl.split("?").shift(). Fonte: stackoverflow.com/a/32118818/2037431
Marcos Pereira

131

Em vez de concatenar as coisas por conta própria, você pode usar a API node.js para URLs e transmitir URL.format()as informações do express.

Exemplo:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}

4
No meu caso, req.get('host')retorna apenas a parte do nome do host , não a porta. Não sei por que, mas agora reuno o número da porta nas configurações e uso o hostnamecampo, em vez de host.
Maxkoryukov 03/08/19

1
Em vez de pathname, acho que você quer dizer path. Que inclui pesquisa / querystring
Félix Sanz

3
Isso não funciona para URLs que possuem uma string de consulta.
21418 Keith

37

Achei um pouco PITA obter o URL solicitado. Não acredito que não há uma maneira mais fácil de expressar. Deve ser apenas req.requested_url

Mas aqui está como eu o defino:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;

variável de porta tem que ser definida?
Amol M Kulkarni

4
Existe req.port? Não está na documentação do Express?
Mitar

Foi mal. Eu assumi que você saberia de que porta você está servindo e definiu isso antes. Vou atualizar o exemplo novamente. Você também pode obtê-lo comreq.app.settings.port
chovy

quando req.protocol está vazio, significa http?
Codebeat 5/08

Este não está incluindo a consulta. Não está completo. A resposta aceita é melhor.
Kostanos

17

Usando url.format :

var url = require('url');

Isso suporta todos os protocolos e inclui o número da porta. Se você não possui uma string de consulta no seu originalUrl, pode usar esta solução mais limpa:

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

Se você tiver uma sequência de consultas:

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

16

Aqui está uma ótima maneira de adicionar uma função que você pode chamar no objeto req para obter o URL

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

Agora você tem uma função que pode chamar sob demanda, se precisar.


2
Isso não inclui a senha user: que você pode obter em um URL completo ' user: pass@host.com: 8080 / p / a / t / h? Query = string # hash '
Codifique exclusivamente

@CodeUniquely true, mas desde que essa convenção foi descontinuada há mais de uma década, espero que ninguém esteja realmente criando especificações de informações do usuário em suas APIs.
Mike

11

efetivar req.host/req.hostname deve ter duas condições quando o Express behind proxies :

  1. app.set('trust proxy', 'loopback'); no app.js
  2. X-Forwarded-HostO cabeçalho deve ser especificado por você no servidor da web. por exemplo. 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
sim, ninguém disse que, se você não tem a configuração correta no Apache ou nginx, você vai ter 127.0.0.1a partir dereq.get('host')
Spark.Bao


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

ou

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

6

Você precisa construí-lo usando req.headers.host + req.url. Obviamente, se você estiver hospedando em uma porta diferente, você entenderá ;-)


1
Isso me dá tudo, menos o protocolo ... há algo que possa me dizer isso?
Chris Abrams

Para obter o protocolo, use:req.protocol
mrded

6

Eu sugeriria usar originalUrl em vez de URL:

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

Veja a descrição do originalUrl aqui: http://expressjs.com/api.html#req.originalUrl

Em nosso sistema, fazemos algo assim, portanto o originalUrl é importante para nós:

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

blah_controller aparece assim:

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

Portanto, nossos URLs têm o formato:

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

Portanto, precisamos req.originalUrl no controlador de barras get handler.


6

Meu código fica assim,

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


5

Eu uso o pacote de nós 'url' (npm install url)

O que faz é quando você chama

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

isso lhe dará a possibilidade de recuperar todo ou parte do URL. Mais informações aqui: https://github.com/defunctzombie/node-url

Usei-o da seguinte maneira para obter o que vem depois do / no http://www.example.com/ para usar como variável e criar um perfil específico (como o facebook: http: //www.facebook. com / nome de usuário )

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

Embora para que isso funcione, você deve criar sua rota dessa maneira no arquivo server.js:

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

E defina seu arquivo de rota desta maneira:

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

2

Você pode usar esta função na rota 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.protocolfornecerá http ou https, req.headers.hostfornecerá o nome completo do host, como www.google.com, req.originalUrlfornecerá o restante pathName(no seu caso /one/two)


Você poderia elaborar como essa solução funciona. Evite postar apenas respostas de código no estouro de pilha.
Arcath

@Arcath elaborado.
Awais Ayub

1

Obrigado a todos por esta informação. Isso é incrivelmente irritante.

Adicione isso ao seu código e você nunca mais precisará pensar sobre isso:

var app = express();

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

Você também pode fazer ou definir outras coisas, como fazer logon no console.


0

Apenas o código abaixo foi suficiente para mim!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.