Jak uzyskać pełny adres URL w Express?


486

Powiedzmy, że mój przykładowy adres URL to

http://example.com/one/two

i mówię, że mam następującą trasę

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

Wartość urlbędzie /one/two.

Jak uzyskać pełny adres URL w Express? Na przykład w powyższym przypadku chciałbym otrzymać http://example.com/one/two.


6
Do twojej wiadomości możesz sprawdzić obiekt żądania i przejrzeć, ale jestem hipokrytą i znalazłem go tutaj.
Jason Sebring

Odpowiedzi:


742
  1. Protokół jest dostępny jako req.protocol. dokumenty tutaj

    1. Przed Express 3.0 protokół, który możesz założyć, httpchyba że zobaczysz, że req.get('X-Forwarded-Protocol')jest ustawiony i ma wartość https, w którym to przypadku wiesz, że to twój protokół
  2. Host pochodzi z, req.get('host')jak wskazał Gopal

  3. Mamy nadzieję, że nie potrzebujesz niestandardowego portu w swoich adresach URL, ale gdybyś musiał to wiedzieć, miałby to stan aplikacji, ponieważ jest to wszystko, co przekazałeś app.listenw momencie uruchamiania serwera. Jednak w przypadku programowania lokalnego na niestandardowym porcie Chrome wydaje się zawierać port w nagłówku hosta, więc na przykład req.get('host')zwraca localhost:3000. Tak więc przynajmniej w przypadku witryny produkcyjnej na standardowym porcie i przeglądania bezpośrednio do Twojej aplikacji ekspresowej (bez odwrotnego proxy), hostnagłówek wydaje się robić właściwą rzecz w odniesieniu do portu w adresie URL.

  4. Ścieżka pochodzi z req.originalUrl(dzięki @pgrassant). Zauważ, że NIE zawiera ciągu zapytania. Dokumenty tutaj na req.url i req.originalUrl . W zależności od tego, co zamierzasz zrobić z adresem URL, originalUrlmoże być lub nie być poprawną wartością w porównaniu do req.url.

Połącz je wszystkie, aby zrekonstruować bezwzględny adres URL.

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

3
@dave klient może wysyłać dowolne nagłówki (jak również adresy URL, porty, losowe śmieci inne niż HTTP), jednak w pewnym momencie fałszywe lub niedokładne nagłówki po prostu spowodują awarię protokołu. Na przykład w środowisku wirtualnego hosta niepoprawny nagłówek „hosta” wyświetla zupełnie inną stronę internetową. W przypadku X-Forwarded-Protocol zwykle nie jest wysyłany przez rzeczywistego klienta (przeglądarkę), ale przez zwrotny serwer proxy (nginx / varnish / apache / cokolwiek), który obsługuje HTTPS przed aplikacją.
Peter Lyons,

59
Lub użyj req.get('Host')zamiast tego req.hostdaje hosta i sekcję portu.
diosney

1
Prawdopodobnie najlepiej zadać osobne pytanie. To pytanie dotyczy ekspresu.
Peter Lyons,

18
hostParametr w nagłówku żądania mogą być sfałszowane. Istnieje możliwość „ataku nagłówkiem hosta”, jeśli używasz w res.hostten sposób. W środowisku Django mają zmienną „dozwolone hosty”, która służy do zapobiegania takiemu atakowi. Używam zmiennej konfiguracyjnej, która jest moja, root_urlktórą można dodać do req.urluzupełnienia. O ataku: skeletonscribe.net/2013/05/…
Amir Eldor

1
Jeśli chcesz dodać req.originalUrlbez parametrów, po prostu zrób req.originalUrl.split("?").shift(). Źródło: stackoverflow.com/a/32118818/2037431
Marcos Pereira

131

Zamiast łączyć rzeczy razem, możesz zamiast tego użyć API node.js dla adresów URL i przekazać URL.format()informacje z ekspresu.

Przykład:

var url = require('url');

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

4
W moim przypadku req.get('host')zwraca tylko część nazwy hosta , a nie port. Nie wiem dlaczego, ale teraz zbieram numer portu z ustawień i używam hostnamepola zamiast host.
maxkoryukov

1
Zamiast tego pathnamemyślę, że masz na myśli path. Który obejmuje wyszukiwanie / kwerendę
Félix Sanz

3
To nie działa w przypadku adresów URL zawierających ciąg zapytania.
Keith

37

Znalazłem trochę PITA, aby uzyskać żądany adres URL. Nie mogę uwierzyć, że nie ma łatwiejszego sposobu na ekspresowe. Powinien być tylko wymagany.wymagany_url

Ale oto jak to ustawiłem:

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

zmienna portu musi być zdefiniowana?
Amol M. Kulkarni

4
Czy req.portistnieje Nie ma go w dokumentacji Express?
Mitar

Mój błąd. Zakładałem, że będziesz wiedział, z którego portu służysz, i ustawiłeś to wcześniej. Zaktualizuję przykład ponownie. Możesz go również uzyskać za pomocąreq.app.settings.port
chovy

kiedy wymagana wartość protokołu jest pusta, czy oznacza to http?
Codebeat

Ten nie obejmuje zapytania. To nie jest kompletne. Przyjmowana odpowiedź jest lepsza.
Kostanos,

17

Za pomocą url.format :

var url = require('url');

Obsługuje wszystkie protokoły i zawiera numer portu. Jeśli nie masz ciągu zapytania w originalUrl, możesz użyć tego czystszego rozwiązania:

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

Jeśli masz ciąg zapytania:

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

16

Oto świetny sposób na dodanie funkcji, którą można wywołać na obiekcie req w celu uzyskania adresu URL

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

Teraz masz funkcję, którą możesz wywołać na żądanie, jeśli jej potrzebujesz.


2
Nie obejmuje to użytkownika: hasło, które można uzyskać w pełnym adresie URL „ użytkownik: pass@host.com: 8080 / p / a / t / h? Query = string # hash
kod jednoznacznie

@Code Wyjątkowo prawda, ale ponieważ ta konwencja jest przestarzała już od ponad dekady, mam nadzieję, że nikt tak naprawdę nie buduje specyfikacji użytkownika w swoich interfejsach API
Mike

11

aby req.host/req.hostname działał, muszą mieć dwa warunki, gdy Express za serwerami proxy :

  1. app.set('trust proxy', 'loopback'); w app.js
  2. X-Forwarded-Hostnagłówek musi być określony przez Ciebie na serwerze internetowym. na przykład. 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
tak, nikt nie powiedział, że jeśli nie masz poprawnej konfiguracji w apache lub nginx, dostaniesz 127.0.0.1odreq.get('host')
Spark.Bao


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

lub

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

6

Musisz go zbudować za pomocą req.headers.host + req.url. Oczywiście, jeśli hostujesz w innym porcie i taki masz pomysł ;-)


1
To daje mi wszystko oprócz protokołu ... czy jest coś, co może mi to powiedzieć?
Chris Abrams,

Aby uzyskać protokół, użyj:req.protocol
mrded

6

Sugerowałbym użycie originalUrl zamiast adresu URL:

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

Zobacz opis originalUrl tutaj: http://expressjs.com/api.html#req.originalUrl

W naszym systemie robimy coś takiego, więc originalUrl jest dla nas ważny:

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

blah_controller wygląda następująco:

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

Nasze adresy URL mają więc format:

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

Dlatego potrzebujemy req.originalUrl w kontrolerze pasków get handler.


6

Mój kod wygląda tak

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


5

Korzystam z pakietu węzła „url” (npm url install)

To, co robi, to kiedy dzwonisz

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

da ci to możliwość odzyskania całości lub części adresu URL. Więcej informacji tutaj: https://github.com/defunctzombie/node-url

Użyłem go w następujący sposób, aby uzyskać wszystko, co następuje po / w http://www.example.com/, aby użyć go jako zmiennej i wyświetlić konkretny profil (coś w rodzaju facebooka: http: //www.facebook. com / nazwa użytkownika )

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

Aby to zadziałało, musisz utworzyć swoją trasę w ten sposób w pliku server.js:

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

I ustaw plik trasy w ten sposób:

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

2

Możesz użyć tej funkcji na takiej trasie

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.protocolpoda adres http lub https, req.headers.hostpoda pełną nazwę hosta, taką jak www.google.com, req.originalUrlpoda resztę pathName(w twoim przypadku /one/two)


Czy możesz wyjaśnić, jak działa to rozwiązanie. Unikaj publikowania kodów tylko w przypadku przepełnienia stosu.
Arcath,

@Arcath opracowane.
Awais Ayub,

1

Dziękuję wszystkim za tę informację. To jest niezwykle denerwujące.

Dodaj to do swojego kodu i już nigdy nie będziesz musiał o tym myśleć:

var app = express();

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

Możesz tam też wykonywać inne czynności, np. Logować do konsoli.


0

Tylko poniższy kod był dla mnie wystarczający!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.