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.