Jaka jest różnica między zmiennymi Nginx $ host, $ http_host i $ nazwa_serwera?

42

Jaka jest różnica między tymi trzema zmiennymi Nginx $host, $http_hosti $server_name?

Mam regułę przepisywania, w której nie jestem pewien, której powinienem użyć:

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

Szukam odpowiedzi, która nie mówi tylko „użyj zmiennej ___ w regule przepisywania”, ale także wyjaśnia teoretyczne różnice między nimi.

Jeff Widman
źródło
Zrozumiałem później, że nawet nie musiałem określać $schemei $host... return 301 /forum/index.php?posts/$arg_p/;działa dobrze.
Jeff Widman,
Większość przeglądarek działałaby ze względnym adresem URL w przekierowaniu, ale standardowy ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) wymaga bezwzględnego adresu URL w Locationnagłówku.
Cthulhu,

Odpowiedzi:

54

Prawie zawsze powinieneś używać $host, ponieważ jest to jedyna gwarancja posiadania czegoś sensownego niezależnie od tego, jak zachowuje się klient użytkownika, chyba że potrzebujesz semantyki jednej z pozostałych zmiennych.

Różnicę wyjaśniono w dokumentacji nginx :

  • $host zawiera „w następującej kolejności: nazwa hosta z wiersza żądania, nazwa hosta z pola nagłówka żądania„ Host ”lub nazwa serwera pasująca do żądania”
  • $http_host zawiera zawartość pola nagłówka HTTP „Host”, jeśli była obecna w żądaniu
  • $server_namezawiera server_namewirtualny host, który przetworzył żądanie, tak jak zostało zdefiniowane w konfiguracji nginx. Jeśli a serverzawiera wiele server_names, tylko pierwsza będzie obecna w tej zmiennej.

Ponieważ klienty użytkownika mogą wysyłać nazwę hosta w wierszu żądania, a nie w nagłówku Host:, choć jest to rzadko wykonywane, z wyjątkiem łączenia się z serwerami proxy, należy to uwzględnić.

Musisz także wziąć pod uwagę przypadek, w którym klient użytkownika w ogóle nie wysyła nazwy hosta, np. Stare żądania HTTP / 1.0 i nowoczesne źle napisane oprogramowanie. Możesz to zrobić, przekierowując je do hosta wirtualnego typu catch-all, który niczego nie obsługuje, jeśli obsługujesz wiele witryn internetowych lub jeśli masz tylko jedną witrynę internetową na serwerze, możesz przetwarzać wszystko za pośrednictwem jednego hosta wirtualnego . W tym drugim przypadku również musisz to uwzględnić.

Tylko $hostzmienna uwzględnia wszystkie możliwe rzeczy, które klient użytkownika może zrobić podczas tworzenia żądania HTTP.

Michael Hampton
źródło
2
Z drugiej strony $server_namejest bezpieczny, gdy Host:pole z UA może zawierać dowolną treść.
Cthulhu,
1
Czy zmieniono nazwę $ http_host na $ nazwa hosta? Nie mogę znaleźć takiej zmiennej w dokumencie Nginx. Nazwa hosta $ jest najbardziej podobna.
darkbaby123
3
@ darkbaby123 Nie, nie zmieniono nazwy na nic. Zobacz dokumentację .
Michael Hampton
1
Ach, teraz rozumiem, co oznacza zmienna http_ <nazwa>. Dziękuję Ci!
darkbaby123
0

Chciałbym dodać kolejny ważny punkt niewymieniony w zaakceptowanej odpowiedzi.

$hostczy nie mają numer portu, natomiast $http_hostzawierają numer portu.

edycja : nie zawsze.

Zawsze ustawiam nagłówek „add_header Y-blog-http_host” $ http_host ”;”

Następnie curl -I -L domain.com:80(lub 443) i nagłówek w ogóle nie pokazuje numeru portu. Zweryfikowano za pomocą nginx-extra 1.10.3. Czy to dlatego, że jest to typowe porty http lub konfiguracja Nginx? Ten komentarz, żeby powiedzieć, że nie zawsze zachowuje się tak, jak myślisz.

Mohammed Noureldin
źródło
0

Zmagałem się również z tym przez jakiś czas. Stało się jasne, gdy zrozumiałem, że $ http_XXXXX odnosi się do wszystkich zadeklarowanych zmiennych nagłówka.

Tak więc $ http_user_agent, $ http_referer to „USER AGENT”, „REFERER” wymieniony małymi i małymi literami. To wyjaśniło mi, skąd do diabła pochodzi $ http_upgrade w wielu przykładach konfiguracji NGINX.

Przeczytaj to na https://stackoverflow.com/questions/15414810/whats-the-difference-of-host-and-http-host-in-nginx

luison
źródło