¿Cuál es la diferencia entre las variables Nginx $ host, $ http_host y $ server_name?

42

¿Cuál es la diferencia entre las tres variables Nginx $host, $http_hosty $server_name?

Tengo una regla de reescritura donde no estoy seguro de cuál debería usar:

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

Estoy buscando una respuesta que no solo diga 'use ___ variable en su regla de reescritura' sino que también explique las diferencias teóricas entre ellos.

Jeff Widman
fuente
Más tarde me di cuenta de que ni siquiera necesitaba especificar $schemey $host... return 301 /forum/index.php?posts/$arg_p/;funciona bien.
Jeff Widman
La mayoría del navegador funcionaría con URL relativa en la redirección, pero el estándar ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) requiere una URL absoluta en el Locationencabezado.
Cthulhu

Respuestas:

54

Casi siempre debe usar $host, ya que es el único garantizado para tener algo sensible, independientemente de cómo se comporta el agente de usuario, a menos que necesite específicamente la semántica de una de las otras variables.

La diferencia se explica en la documentación de nginx :

  • $host contiene "en este orden de precedencia: nombre de host de la línea de solicitud, o nombre de host del campo de encabezado de solicitud 'Host', o el nombre del servidor que coincide con una solicitud"
  • $http_host contiene el contenido del campo de encabezado HTTP "Host", si estaba presente en la solicitud
  • $server_namecontiene el server_namedel host virtual que procesó la solicitud, tal como se definió en la configuración de nginx. Si a servercontiene múltiples server_names, solo el primero estará presente en esta variable.

Dado que es legal que los agentes de usuario envíen el nombre de host en la línea de solicitud en lugar de en un encabezado Host: aunque rara vez se hace, excepto cuando se conecta a servidores proxy, debe tener esto en cuenta.

También debe tener en cuenta el caso en el que el agente de usuario no envía un nombre de host en absoluto, por ejemplo, solicitudes HTTP / 1.0 antiguas y software moderno mal escrito. Puede hacerlo desviándolos a un host virtual general que no sirve nada, si está sirviendo múltiples sitios web, o si solo tiene un único sitio web en su servidor, puede procesar todo a través de un único host virtual . En este último caso, también debe tener esto en cuenta.

Solo la $hostvariable tiene en cuenta todas las cosas posibles que un agente de usuario puede hacer al formar una solicitud HTTP.

Michael Hampton
fuente
2
Por otro lado, $server_namees seguro cuando el Host:campo de UA puede contener contenido arbitrario.
Cthulhu
1
¿Se ha cambiado el nombre de $ http_host a $ hostname? No puedo encontrar esa variable en Nginx doc. $ hostname es el más similar, supongo.
darkbaby123
3
@ darkbaby123 No, no fue renombrado a nada. Ver la documentación .
Michael Hampton
1
Ah, ahora entiendo lo que significa http_ <nombre> variable. ¡Gracias!
darkbaby123
0

Me gustaría agregar otro punto importante no mencionado en la respuesta aceptada.

$hostno no tienen número de puerto, mientras que $http_hostsí incluyen el número de puerto.

editar : no siempre

Configuré un encabezado "add_header Y-blog-http_host" $ http_host "siempre;"

Luego curl -I -L domain.com:80(o 443) y el encabezado no muestra ningún número de puerto. Verificado con nginx-extra 1.10.3. ¿Es porque se trata de puertos http (s) comunes o configuración nginx? Este comentario solo para decir que las cosas no siempre se comportan como piensas.

Mohammed Noureldin
fuente