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.


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;

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
  });
}

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;

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);

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.


2
Ini tidak termasuk pengguna: kata sandi yang dapat Anda peroleh dalam url lengkap pengguna: pass@host.com: 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>


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


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

atau

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

6

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


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.


6

Kode saya terlihat seperti ini,

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


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
}

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)


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.


0

Hanya kode di bawah ini sudah cukup bagiku!

const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.