Express'te tam url nasıl edinilir?


486

Diyelim ki örnek URL'm

http://example.com/one/two

ve diyorum ki şu rotaya sahibim

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

Değeri urlolacak /one/two.

Express'teki URL'nin tamamını nasıl edinebilirim ? Örneğin, yukarıdaki durumda, almak istiyorum http://example.com/one/two.


6
FYI istek nesnesini inceleyebilir ve bakabilirsiniz ama ben bir ikiyüzlüyüm ve burada buldum.
Jason Sebring

Yanıtlar:


742
  1. Protokol olarak kullanılabilir req.protocol. buradaki dokümanlar

    1. Express 3.0'dan önce , ayarlandığını ve değere sahip httpolduğunu görmediğiniz sürece kabul edebileceğiniz protokol , bu durumda protokolünüzün olduğunu bilirsinizreq.get('X-Forwarded-Protocol')https
  2. Ev sahibi req.get('host')Gopal'ın belirttiği gibi geliyor

  3. Umarım URL'lerinizde standart olmayan bir bağlantı noktasına ihtiyacınız yoktur, ancak bunu bilmeniz gerekiyorsa, bunu uygulama durumunuzda görürsünüz, çünkü app.listensunucu başlangıç ​​zamanında geçtiğiniz her şeydir . Bununla birlikte, standart dışı bir bağlantı noktasında yerel geliştirme durumunda, Chrome bağlantı noktasını ana bilgisayar başlığına req.get('host')eklediğinden localhost:3000, örneğin, geri döner . Bu nedenle, en azından standart bir bağlantı noktasındaki bir üretim sitesi ve doğrudan ekspres uygulamanıza (ters proxy olmadan) göz atmak için, hostbaşlık URL'deki bağlantı noktasıyla ilgili doğru şeyi yapıyor gibi görünüyor.

  4. Yol geliyor req.originalUrl(teşekkürler @pgrassant). Bunun sorgu dizesini içerdiğini unutmayın. req.url ve req.originalUrl üzerindeki belgeler . URL ile ne yapmak istediğinize bağlı originalUrlolarak, karşılaştırıldığında doğru değer olabilir veya olmayabilir req.url.

Mutlak URL'yi yeniden oluşturmak için bunları bir araya getirin.

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

3
@dave bir istemci istediği her başlığı (URL, bağlantı noktası, rasgele HTTP olmayan çöp) gönderebilir, ancak bir noktada sahte veya yanlış üstbilgiler yalnızca protokolün başarısız olmasına neden olur. Örneğin, sanal bir ana bilgisayar ortamında, yanlış bir "ana bilgisayar" başlığı tamamen farklı bir web sitesi görüntüler. X-Forwarded-Protocol durumunda, bu genellikle gerçek istemci (tarayıcı) tarafından değil, uygulamanızın önünde HTTPS'ye hizmet veren ters proxy (nginx / varnish / apache / whatever) tarafından gönderilir.
Peter Lyons

59
Veya ana bilgisayar ve bağlantı noktası bölümünü veren req.get('Host')bunun yerine kullanın req.host.
diosney

1
Bunun için ayrı bir soru göndermek muhtemelen en iyisidir. Bu soru ekspres hakkında.
Peter Lyons

18
hostİstek başlıklarına parametre sahte olabilir. res.hostBu şekilde kullanılırsa olası bir "ana bilgisayar üstbilgisi saldırısı" vardır . Django çerçevesinde, böyle bir saldırıyı önlemek için kullanılan 'izin verilen ana makineler' değişkenine sahiptirler. Ben tamamlanması için root_urleklenebilir benim olan bir yapılandırma değişkeni kullanın req.url. Saldırı hakkında: skeletonscribe.net/2013/05/…
Amir Eldor

1
req.originalUrlParametresiz eklemek istiyorsanız , yapmanız yeterlidir req.originalUrl.split("?").shift(). Kaynak: stackoverflow.com/a/32118818/2037431
Marcos Pereira

131

Olayları kendi başınıza birleştirmek yerine, URL'ler için node.js API'sini kullanabilir ve bilgileri express'ten aktarabilirsiniz URL.format().

Misal:

var url = require('url');

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

4
Benim durumumda portu değil, req.get('host')sadece hostname kısmını döndürür . Nedenini bilmiyorum, ama şimdi bağlantı noktası numarasını ayarlardan topluyorum ve hostnameyerine alanı kullanıyorum host.
maxkoryukov

1
Bunun yerine, pathnamedemek istediğini düşünüyorum path. Arama / sorgu dizesini içerir
Félix Sanz

3
Bu, sorgu dizesi olan URL'ler için çalışmaz.
Keith

37

İstenen url almak için bir PITA biraz buldum. Daha kolay ifade edilebileceğine inanamıyorum. Sadece req.requested_url olmalı

Ama işte böyle ayarladım:

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

port değişkeni tanımlanmalı mı?
Amol M Kulkarni

4
Var mı req.port? Express belgelerinde değil mi?
Mitar

Benim hatam. Hangi limanda hizmet verdiğinizi bildiğinizi ve bunu önceden ayarladığınızı varsaydım. Örneği tekrar güncelleyeceğim. Ayrıca alabilirsinizreq.app.settings.port
chovy

req.protocol boş olduğunda, bu http anlamına mı geliyor?
Codebeat

Bu sorgu dahil değildir. Tam değil. Kabul edilen cevap daha iyidir.
Kostanos

17

Url.format kullanma :

var url = require('url');

Bu, tüm protokolleri destekler ve bağlantı noktası numarasını içerir. OriginalUrl'nizde bir sorgu dizesi yoksa bu temiz çözümü kullanabilirsiniz:

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

Bir sorgu dizeniz varsa:

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

16

İşte url almak için req nesnesini çağırabileceğiniz bir işlev eklemenin harika bir yolu

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

Artık ihtiyacınız olduğunda talep üzerine çağırabileceğiniz bir fonksiyonunuz var.



@CodeUniquely true, ancak bu sözleşme on yıldan uzun bir süredir kullanımdan kaldırıldığı için, umarım hiç kimse aslında API'larına userinfo teknik özellikleri oluşturmuyor
Mike

11

req.host/req.hostname'i etkili yapmak, proxy'lerin arkasında Express olduğunda iki koşul olmalıdır :

  1. app.set('trust proxy', 'loopback'); app.js içinde
  2. X-Forwarded-Hostbaşlık web sunucusunda sizin tarafınızdan belirtilmelidir. Örneğin. 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
evet, kimse size apache veya nginx hiçbir doğru yapılandırmayı varsa, alacak, söylendi 127.0.0.1gelenreq.get('host')
Spark.Bao


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

veya

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

6

Bunu kullanarak inşa etmeniz gerekir req.headers.host + req.url. Tabii ki farklı bir limana ev sahipliği yapıyorsanız ve böyle bir fikre sahipseniz ;-)


1
Bu bana protokolden başka her şeyi getirir ... Bunu söyleyebilecek bir şey var mı?
Chris Abrams

Protokolü kullanmak için:req.protocol
mrded

6

URL yerine originalUrl kullanmanızı öneririm:

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

OriginalUrl açıklamasına buradan bakın: http://expressjs.com/api.html#req.originalUrl

Sistemimizde böyle bir şey yapıyoruz, bu yüzden originalUrl bizim için önemlidir:

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

blah_controller şöyle görünür:

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

Yani URL'lerimiz şu biçime sahiptir:

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

Bu nedenle, bar denetleyicisindeki req.originalUrl'e ihtiyacımız var.


6

Kodum şöyle görünüyor,

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


5

Düğüm paketini 'url' kullanıyorum (npm install url)

Aradığın şey

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

size url'nin tamamını veya bir kısmını alma imkanı verir. Daha fazla bilgi burada: https://github.com/defunctzombie/node-url

Değişken olarak kullanmak ve belirli bir profili (tür facebook: http: //www.facebook gibi) çekmek için http://www.example.com/ adresinden sonra gelenleri almak için aşağıdaki şekilde kullandım . com.tr / username )

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

Bunun çalışması için, server.js dosyanızda rotanızı şu şekilde oluşturmanız gerekir:

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

Ve rota dosyanızı şu şekilde ayarlayın:

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

2

Bu işlevi rotada şu şekilde kullanabilirsiniz

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.protocolsize http veya https req.headers.hostverecek, size www.google.com gibi tam ana bilgisayar adını req.originalUrlverecek, geri kalanını verecektir pathName(sizin durumunuzda /one/two)


Bu çözümün nasıl çalıştığını açıklayabilir misiniz? Kodları yalnızca Yığın Taşması üzerine yanıt göndermekten kaçının.
Arcath

@Arcath detaylandırıldı.
Awais Ayub

1

Bu bilgi için hepinize teşekkür ederim. Bu inanılmaz derecede can sıkıcı.

Bunu kodunuza ekleyin, bir daha asla düşünmek zorunda kalmayacaksınız:

var app = express();

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

Konsolda oturum açma gibi başka şeyler de yapabilir veya ayarlayabilirsiniz.


0

Sadece aşağıdaki kod benim için yeterliydi!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.