Bagaimana cara mendapatkan url lengkap di Express?

486

Katakanlah url sampel saya adalah

http://example.com/one/two

dan saya katakan saya memiliki rute berikut

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

Nilai urlakan /one/two.

Bagaimana cara mendapatkan url lengkap di Express? Misalnya, dalam kasus di atas, saya ingin menerima http://example.com/one/two.

Chris Abrams
sumber
6
FYI Anda dapat memeriksa objek permintaan dan melihat melalui tapi saya munafik dan menemukannya di sini.
Jason Sebring

Jawaban:

742
  1. Protokol tersedia sebagai req.protocol. dokumen di sini

    1. Sebelum express 3.0, protokol yang dapat Anda asumsikan httpkecuali Anda melihat bahwa itu req.get('X-Forwarded-Protocol')telah diatur dan memiliki nilai https, dalam hal ini Anda tahu itu adalah protokol Anda
  2. Tuan rumah datang dari req.get('host')seperti yang ditunjukkan Gopal

  3. Mudah-mudahan Anda tidak memerlukan port non-standar di URL Anda, tetapi jika Anda memang perlu mengetahuinya, Anda akan memilikinya dalam status aplikasi Anda karena itu adalah apa pun yang Anda lewati app.listensaat startup server. Namun, dalam kasus pengembangan lokal pada port non-standar, Chrome tampaknya memasukkan port dalam header host sehingga req.get('host')kembali localhost:3000, misalnya. Jadi setidaknya untuk kasus-kasus sebuah situs produksi pada port standar dan menjelajah langsung ke aplikasi ekspres Anda (tanpa proxy terbalik), hostheader tampaknya melakukan hal yang benar terkait port di URL.

  4. Path berasal dari req.originalUrl(thanks @pgrassant). Catatan ini TIDAK termasuk string kueri. docs di sini di req.url dan req.originalUrl . Bergantung pada apa yang ingin Anda lakukan dengan URL, originalUrlmungkin atau mungkin bukan nilai yang benar dibandingkan dengan req.url.

Gabungkan semuanya untuk merekonstruksi URL absolut.

  var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Peter Lyons
sumber
3
@memiliki klien dapat mengirim tajuk apa pun yang diinginkannya (serta URL apa pun, port, sampah non-HTTP acak), namun, pada beberapa titik tajuk palsu atau tidak akurat hanya akan menyebabkan protokol gagal. Misalnya, di lingkungan host virtual, header "host" yang salah akan menampilkan situs web yang sama sekali berbeda. Dalam kasus X-Forwarded-Protocol, yang biasanya tidak dikirim oleh klien yang sebenarnya (browser) tetapi oleh proksi terbalik (nginx / varnish / apache / apa pun) yang melayani HTTPS di depan aplikasi Anda.
Peter Lyons
59
Atau gunakan req.get('Host')alih-alih req.hostyang memberikan host plus bagian port.
diosney
1
Mungkin terbaik untuk mengirim pertanyaan terpisah untuk itu. Pertanyaan ini tentang ekspres.
Peter Lyons
18
The hostparameter dalam header permintaan dapat palsu. Ada kemungkinan "serangan header host" jika menggunakan res.hostcara ini. Dalam kerangka Django mereka memiliki variabel 'host diizinkan' yang digunakan untuk mencegah serangan tersebut. Saya menggunakan variabel konfigurasi yang saya root_urldapat ditambahkan ke req.urluntuk penyelesaian. Tentang serangan: skeletonscribe.net/2013/05/...
Amir Eldor
1
Jika Anda ingin menambahkan req.originalUrltanpa parameter, cukup lakukan req.originalUrl.split("?").shift(). Sumber: stackoverflow.com/a/32118818/2037431
Marcos Pereira
131

Alih-alih menyatukan semuanya sendiri, Anda bisa menggunakan API node.js untuk URL dan meneruskan URL.format()informasi dari express.

Contoh:

var url = require('url');

function fullUrl(req) {
  return url.format({
    protocol: req.protocol,
    host: req.get('host'),
    pathname: req.originalUrl
  });
}
Michael Weibel
sumber
4
Dalam kasus saya, req.get('host')hanya mengembalikan bagian hostname , bukan port. Tidak tahu mengapa, tapi sekarang saya mengumpulkan nomor port dari pengaturan, dan menggunakan hostnamebidang, bukan host.
maxkoryukov
1
Alih-alih pathname, saya pikir maksud Anda path. Yang termasuk search / querystring
Félix Sanz
3
Ini tidak berfungsi untuk URL yang memiliki string kueri.
Keith
37

Saya menemukan sedikit PITA untuk mendapatkan url yang diminta. Saya tidak percaya tidak ada cara yang lebih mudah dalam mengekspresikan. Seharusnya req.requested_url

Tapi begini cara saya mengaturnya:

var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host  + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
kenyal
sumber
variabel port harus didefinisikan?
Amol M Kulkarni
4
Apakah req.portada Tidak ada dalam dokumentasi Express?
Mitar
Salahku. Saya berasumsi Anda akan tahu port apa yang Anda layani dan atur sebelumnya. Saya akan memperbarui contoh lagi. Anda juga bisa mendapatkannya denganreq.app.settings.port
chovy
ketika req.protocol kosong, apakah ini berarti http?
Codebeat
Yang ini tidak termasuk permintaan. Itu tidak lengkap. Jawaban yang diterima lebih baik.
Kostanos
17

Menggunakan url.format :

var url = require('url');

Ini mendukung semua protokol dan termasuk nomor port. Jika Anda tidak memiliki string kueri di originalUrl Anda, Anda dapat menggunakan solusi bersih ini:

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

Jika Anda memiliki string kueri:

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

Berikut adalah cara yang bagus untuk menambahkan fungsi yang dapat Anda panggil pada objek req untuk mendapatkan url

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

Sekarang Anda memiliki fungsi yang dapat Anda panggil berdasarkan permintaan jika Anda membutuhkannya.

hilang dalam terjemahan
sumber
2
Ini tidak termasuk pengguna: kata sandi yang dapat Anda peroleh dalam url lengkap pengguna: [email protected]: 8080 / p / a / t / h? Query = string # hash '
Kode Uniknya
@CodeUniquely true, tetapi karena konvensi itu telah ditinggalkan selama lebih dari satu dekade sekarang, mudah-mudahan tidak ada yang benar-benar membangun spesifikasi userinfo ke dalam API mereka
Mike
11

membuat req.host/req.hostname efektif harus memiliki dua kondisi ketika Express di belakang proxy :

  1. app.set('trust proxy', 'loopback'); di app.js
  2. X-Forwarded-Hostheader harus ditentukan oleh Anda sendiri di server web. misalnya. 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
sumber
1
ya, tidak ada yang mengatakan bahwa, jika Anda tidak memiliki konfigurasi yang benar di apache atau nginx, Anda akan mendapatkan 127.0.0.1darireq.get('host')
Spark.Bao
10

Gunakan ini,

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

atau

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

Anda perlu membuatnya menggunakan req.headers.host + req.url. Tentu saja jika Anda hosting di port yang berbeda dan Anda mendapatkan ide tersebut ;-)

g13n
sumber
1
Itu membuat saya segalanya kecuali protokolnya ... adakah yang bisa memberi tahu saya tentang itu?
Chris Abrams
Untuk mendapatkan protokol gunakan:req.protocol
mrded
6

Saya sarankan menggunakan originalUrl alih-alih URL:

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

Lihat deskripsi originalUrl di sini: http://expressjs.com/api.html#req.originalUrl

Dalam sistem kami, kami melakukan sesuatu seperti ini, jadi originalUrl penting bagi kami:

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

blah_controller terlihat seperti ini:

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

Jadi URL kami memiliki format:

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

Oleh karena itu, kita perlu req.originalUrl di bar controller get handler.

Amber Haq Dixon
sumber
6

Kode saya terlihat seperti ini,

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

Soomtong
sumber
5

Saya menggunakan paket simpul 'url' (npm install url)

Apa yang dilakukannya adalah ketika Anda menelepon

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

itu akan memberi Anda kemungkinan untuk mengambil semua atau sebagian dari url. Info lebih lanjut di sini: https://github.com/defunctzombie/node-url

Saya menggunakannya dengan cara berikut untuk mendapatkan apa pun yang muncul setelah / di http://www.example.com/ untuk digunakan sebagai variabel dan menarik profil tertentu (seperti facebook: http: //www.facebook. com / nama pengguna )

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

Meskipun ini berfungsi, Anda harus membuat rute Anda dengan cara ini di file server.js Anda:

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

Dan atur file rute Anda dengan cara ini:

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

Anda dapat menggunakan fungsi ini di rute seperti ini

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.protocolakan memberi Anda http atau https, req.headers.hostakan memberi Anda nama host lengkap seperti www.google.com, req.originalUrlakan memberikan sisanya pathName(dalam kasus Anda /one/two)

Awais Ayub
sumber
Bisakah Anda menguraikan cara kerja solusi ini. Hindari posting kode hanya jawaban di Stack Overflow.
Arcath
@ Arc dijelaskan.
Awais Ayub
1

Terima kasih atas informasi ini. Ini sangat menjengkelkan.

Tambahkan ini ke kode Anda dan Anda tidak perlu memikirkannya lagi:

var app = express();

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

Anda dapat melakukan atau mengatur hal-hal lain di sana juga, seperti masuk ke konsol.

Nico
sumber
0

Hanya kode di bawah ini sudah cukup bagiku!

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