Was ist der Unterschied zwischen den Nginx-Variablen $ host, $ http_host und $ servername?

42

Was ist der Unterschied zwischen den drei Nginx Variablen $host, $http_hostund $server_name?

Ich habe eine Regel zum Umschreiben, bei der ich nicht sicher bin, welche ich verwenden soll:

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

Ich suche nach einer Antwort, die nicht nur "benutze ___ Variable in deiner Umschreiberegel" sagt, sondern auch die theoretischen Unterschiede zwischen ihnen erklärt.

Jeff Widman
quelle
Mir wurde später klar, dass ich nicht einmal spezifizieren musste $schemeund $host... gut return 301 /forum/index.php?posts/$arg_p/;funktioniert.
Jeff Widman
Die meisten Browser würden mit relativen URLs in Redirect arbeiten, aber der Standard ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) erfordert eine absolute URL in der LocationKopfzeile.
Cthulhu

Antworten:

54

Sie sollten fast immer verwenden $host, da dies die einzige ist, die unabhängig vom Verhalten des Benutzeragenten einen Sinn ergibt, es sei denn, Sie benötigen speziell die Semantik einer der anderen Variablen.

Der Unterschied wird in der Nginx-Dokumentation erklärt :

  • $host enthält "in dieser Rangfolge: Hostname aus der Anforderungszeile oder Hostname aus dem Anforderungsheaderfeld" Host "oder den Servernamen, der einer Anforderung entspricht"
  • $http_host Enthält den Inhalt des HTTP-Headerfelds "Host", sofern es in der Anforderung vorhanden war
  • $server_nameEnthält den server_namedes virtuellen Hosts, der die Anforderung verarbeitet hat, wie er in der nginx-Konfiguration definiert wurde. Wenn a servermehrere server_names enthält , ist in dieser Variablen nur das erste vorhanden.

Da es für Benutzeragenten zulässig ist, den Hostnamen in der Anforderungszeile und nicht in einem Host: -Header zu senden, müssen Sie dies berücksichtigen, auch wenn dies nur bei der Verbindung mit Proxys geschieht.

Sie müssen auch den Fall berücksichtigen, dass der Benutzeragent überhaupt keinen Hostnamen sendet, z. B. alte HTTP / 1.0-Anforderungen und moderne, schlecht geschriebene Software. Sie können dies tun, indem Sie sie an einen virtuellen Catch-All-Host umleiten, der nichts bedient, wenn Sie mehrere Websites bedienen oder wenn Sie nur eine einzige Website auf Ihrem Server haben, können Sie alles über einen einzelnen virtuellen Host verarbeiten . Im letzteren Fall müssen Sie dies ebenfalls berücksichtigen.

Nur die $hostVariable berücksichtigt alle möglichen Aktionen, die ein Benutzeragent beim Bilden einer HTTP-Anforderung ausführen kann.

Michael Hampton
quelle
2
Andererseits ist das $server_namesicher, wenn ein Host:Feld von UA ​​beliebigen Inhalt enthalten kann.
Cthulhu
1
Wird $ http_host in $ hostname umbenannt? Ich kann eine solche Variable in Nginx doc nicht finden. $ hostname ist wohl der ähnlichste.
darkbaby123
3
@ darkbaby123 Nein, es wurde in nichts umbenannt. Siehe die Dokumentation .
Michael Hampton
1
Ah jetzt verstehe ich, was http_ <Name> Variable bedeutet. Danke!
Darkbaby123
0

Ich möchte einen weiteren wichtigen Punkt hinzufügen, der in der akzeptierten Antwort nicht erwähnt wird.

$hostSie NICHT Portnummer haben, während $http_hostDO die Portnummer enthalten.

bearbeiten : nicht immer.

Ich habe immer einen Header "add_header Y-blog-http_host" $ http_host "eingerichtet."

Dann curl -I -L domain.com:80(oder 443) und der Header zeigen überhaupt keine Portnummer an. Verifiziert mit nginx-extra 1.10.3. Liegt es daran, dass es sich um gebräuchliche http (s) -Ports oder Nginx-Konfigurationen handelt? Dieser Kommentar soll nur sagen, dass sich die Dinge nicht immer so verhalten, wie Sie denken.

Mohammed Noureldin
quelle