Apa perbedaan antara variabel Nginx $ host, $ http_host, dan $ server_name?

42

Apa perbedaan antara tiga variabel Nginx $host, $http_hostdan $server_name?

Saya memiliki aturan penulisan ulang di mana saya tidak yakin mana yang harus saya gunakan:

location = /vb/showthread.php {
    # /vb/showthread.php?50271-What-s-happening&p=846039
    if ($arg_p) {
        return 301 $scheme://$host/forum/index.php?posts/$arg_p/;
        }

Saya mencari jawaban yang tidak hanya mengatakan 'gunakan variabel ___ dalam aturan penulisan ulang Anda' tetapi juga menjelaskan perbedaan teoritis di antara mereka.

Jeff Widman
sumber
Saya menyadari kemudian saya bahkan tidak perlu menentukan $schemedan $host... return 301 /forum/index.php?posts/$arg_p/;berfungsi dengan baik.
Jeff Widman
Sebagian besar browser akan berfungsi dengan URL relatif dalam pengalihan, tetapi standar ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) memerlukan URL absolut di Locationheader.
Cthulhu

Jawaban:

54

Anda harus hampir selalu menggunakan $host, karena itu satu-satunya yang dijamin memiliki sesuatu yang masuk akal terlepas dari bagaimana agen-pengguna berperilaku, kecuali jika Anda secara khusus membutuhkan semantik dari salah satu variabel lain.

Perbedaannya dijelaskan dalam dokumentasi nginx :

  • $host mengandung "dalam urutan prioritas ini: nama host dari baris permintaan, atau nama host dari bidang tajuk permintaan 'Host', atau nama server yang cocok dengan permintaan"
  • $http_host berisi konten bidang header "Host" HTTP, jika ada dalam permintaan
  • $server_nameberisi server_namehost virtual yang memproses permintaan, seperti yang didefinisikan dalam konfigurasi nginx. Jika a serverberisi banyak server_names, hanya yang pertama yang akan hadir dalam variabel ini.

Karena agen pengguna sah untuk mengirim nama host di baris permintaan alih-alih di header Host: meskipun jarang dilakukan kecuali saat menghubungkan ke proxy, Anda harus bertanggung jawab untuk ini.

Anda juga harus memperhitungkan kasus di mana agen-pengguna tidak mengirim nama host sama sekali, misalnya permintaan HTTP / 1.0 kuno dan perangkat lunak modern yang ditulis dengan buruk. Anda dapat melakukannya dengan mengalihkan mereka ke host virtual catch-all yang tidak melayani apa pun, jika Anda melayani beberapa situs web, atau jika Anda hanya memiliki satu situs web di server Anda, Anda dapat memproses semuanya melalui satu host virtual . Dalam kasus yang terakhir Anda harus memperhitungkan ini juga.

Hanya $hostvariabel yang bertanggung jawab atas semua hal yang mungkin dilakukan agen pengguna saat membentuk permintaan HTTP.

Michael Hampton
sumber
2
Di sisi lain, $server_nameaman saat Host:bidang dari UA dapat berisi konten sewenang-wenang.
Cthulhu
1
Apakah $ http_host diganti nama menjadi $ hostname? Saya tidak dapat menemukan variabel seperti itu di Nginx doc. $ hostname adalah yang paling mirip, saya kira.
darkbaby123
3
@ darkbaby123 Tidak, tidak diubah namanya menjadi apa pun. Lihat dokumentasi .
Michael Hampton
1
Ah sekarang saya mengerti apa arti variabel http_ <nama>. Terima kasih!
darkbaby123
0

Saya ingin menambahkan poin penting lain yang tidak disebutkan dalam jawaban yang diterima.

$hostjangan TIDAK memiliki nomor port, sedangkan $http_hostDO termasuk nomor port.

sunting : tidak selalu.

Saya mengatur tajuk "add_header Y-blog-http_host" $ http_host "always;"

Lalu curl -I -L domain.com:80(atau 443) dan header tidak menunjukkan nomor port sama sekali. Diverifikasi dengan nginx-ekstra 1.10.3. Apakah karena ini adalah port http (s) umum atau konfigurasi nginx? Komentar ini hanya untuk mengatakan sesuatu tidak selalu berperilaku seperti yang Anda pikirkan.

Mohammed Noureldin
sumber