Quelle est la différence entre les variables Nginx $ host, $ http_host et $ server_name?

42

Quelle est la différence entre les trois variables Nginx $host, $http_host, et $server_name?

J'ai une règle de réécriture pour laquelle je ne suis pas sûr de celle que je devrais utiliser:

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

Je cherche une réponse qui ne se contente pas de dire "utiliser la variable ___ dans votre règle de réécriture", mais explique également les différences théoriques qui les séparent.

Jeff Widman
la source
J'ai réalisé plus tard que je n'avais même pas besoin de préciser $schemeet $host… ça return 301 /forum/index.php?posts/$arg_p/;fonctionnait bien.
Jeff Widman
La plupart des navigateurs fonctionnent avec une URL relative dans la redirection, mais la norme ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) requiert une url absolue dans l'en- Locationtête.
Cthulhu

Réponses:

55

Vous devriez presque toujours utiliser $host, car c'est la seule garantie d'avoir quelque chose de sensé, quel que soit le comportement de l'agent utilisateur, à moins que vous n'ayez spécifiquement besoin de la sémantique de l'une des autres variables.

La différence est expliquée dans la documentation nginx :

  • $host contient "dans cet ordre de priorité: nom d'hôte de la ligne de requête ou nom d'hôte du champ d'en-tête de requête 'Hôte' ou nom du serveur correspondant à une requête"
  • $http_host contient le contenu du champ d'en-tête HTTP "Host", s'il était présent dans la requête
  • $server_namecontient le nom server_namede l'hôte virtuel qui a traité la demande, tel qu'il a été défini dans la configuration de nginx. Si a servercontient plusieurs server_names, seul le premier sera présent dans cette variable.

Puisqu'il est légal pour les agents utilisateurs d'envoyer le nom d'hôte dans la ligne de demande plutôt que dans un en-tête Host:, bien que cela soit rarement fait, sauf lorsque vous vous connectez à des mandataires, vous devez en rendre compte.

Vous devez également prendre en compte le cas où l'agent utilisateur n'envoie pas du tout un nom d'hôte, par exemple des requêtes HTTP / 1.0 anciennes et un logiciel moderne mal écrit. Vous pouvez le faire en les transférant vers un hôte virtuel fourre-tout qui ne sert à rien, si vous servez plusieurs sites Web ou si vous n'avez qu'un seul site Web sur votre serveur, vous pouvez tout traiter via un seul hôte virtuel. . Dans ce dernier cas, vous devez également en tenir compte.

Seule la $hostvariable rend compte de toutes les tâches qu'un agent utilisateur peut faire lors de la création d'une requête HTTP.

Michael Hampton
la source
2
D'autre part, le champ $server_nameest sécurisé lorsque le Host:champ de l'agent utilisateur peut contenir du contenu arbitraire.
Cthulhu
1
Est-ce que $ http_host est renommé en $ hostname? Je ne trouve pas cette variable dans la documentation Nginx. $ hostname est le plus similaire, je suppose.
darkbaby123
3
@ darkbaby123 Non, cela n'a été renommé. Voir la documentation .
Michael Hampton
1
Ah maintenant je comprends ce que signifie http_ <nom>. Merci!
darkbaby123
0

Je voudrais ajouter un autre point important non mentionné dans la réponse acceptée.

$hostne PAS avoir le numéro de port, alors $http_hostincluez le numéro de port.

edit : pas toujours.

J'ai mis en place un en-tête "add_header Y-blog-http_host" $ http_host "toujours;"

Ensuite curl -I -L domain.com:80(ou 443) et l’en-tête n’indique aucun numéro de port. Vérifié avec nginx-extra 1.10.3. C’est parce qu’il s’agit de ports http (s) communs ou de la configuration nginx? Ce commentaire, juste pour dire que les choses ne se comportent pas toujours comme vous le pensez.

Mohammed Noureldin
la source
0

J'ai aussi lutté avec cela pendant un moment. Il est devenu clair quand j'ai compris que $ http_XXXXX se rapportait à toutes les variables d'en-tête déclarées.

Ainsi, $ http_user_agent, $ http_referer sont "USER AGENT", "REFERER" référencés en minuscule et sous-barre oblique. Cela m'a expliqué d'où venait l'enfer $ http_upgrade dans de nombreux exemples de configuration NGINX.

Lisez-le sur https://stackoverflow.com/questions/15414810/whats-the-difference-of-host-and-http-host-in-nginx

luison
la source