В чем разница между переменными Nginx $ host, $ http_host и $ server_name?

42

В чем разница между этими тремя переменными Nginx $host, $http_hostи $server_name?

У меня есть правило перезаписи, где я не уверен, какой из них мне следует использовать:

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

Я ищу ответ, который не просто говорит «используйте переменную ___ в вашем правиле перезаписи», но также объясняет теоретические различия между ними.

Джефф Видман
источник
Позже я понял, что мне даже не нужно было указывать $schemeи $host... return 301 /forum/index.php?posts/$arg_p/;отлично работает.
Джефф Видман
Большинство браузеров будут работать с относительным URL при перенаправлении, но стандарт ( w3.org/Protocols/rfc2616/rfc2616-sec14.html ) требует абсолютного URL в Locationзаголовке.
Ктулху

Ответы:

55

Вы должны почти всегда использовать его $host, так как гарантированно есть единственное, что имеет смысл, независимо от того, как ведет себя пользовательский агент, если только вам конкретно не нужна семантика одной из других переменных.

Разница объясняется в документации по nginx :

  • $host содержит «в таком порядке приоритета: имя хоста из строки запроса или имя хоста из поля заголовка запроса« Хост », или имя сервера, соответствующее запросу»
  • $http_host содержит содержимое поля заголовка HTTP «Host», если оно присутствовало в запросе
  • $server_nameсодержит server_nameвиртуальный хост, который обработал запрос, как это было определено в конфигурации nginx. Если a serverсодержит несколько server_names, в этой переменной будет присутствовать только первый.

Так как пользовательские агенты могут отправлять имя хоста в строке запроса, а не в заголовке Host:, хотя это делается редко, за исключением случаев подключения к прокси-серверам, вы должны учитывать это.

Вы также должны учитывать случай, когда пользовательский агент вообще не отправляет имя хоста, например, древние запросы HTTP / 1.0 и современное плохо написанное программное обеспечение. Вы можете сделать это, перенаправив их на универсальный виртуальный хост, который ничего не обслуживает, если вы обслуживаете несколько веб-сайтов или если у вас только один веб-сайт на вашем сервере, вы можете обрабатывать все через один виртуальный хост , В последнем случае вы должны это учитывать.

Только $hostпеременная учитывает все возможные действия, которые пользовательский агент может выполнять при формировании HTTP-запроса.

Майкл Хэмптон
источник
2
С другой стороны, $server_nameбезопасно, когда Host:поле из UA может содержать произвольный контент.
Ктулху
1
$ Http_host переименован в $ hostname? Я не могу найти такую ​​переменную в Nginx doc. $ hostname самый похожий, я думаю.
darkbaby123
3
@ darkbaby123 Нет, он ни к чему не был переименован. Смотрите документацию .
Майкл Хэмптон
1
Ах, теперь я понимаю, что означает переменная http_ <name>. Спасибо!
darkbaby123
0

Я хотел бы добавить еще один важный момент, не упомянутый в принятом ответе.

$hostделать НЕ имеют номер порта, в то время как $http_hostDO включать номер порта.

редактировать : не всегда.

Я установил заголовок "add_header Y-blog-http_host" $ http_host "всегда;"

Тогда curl -I -L domain.com:80(или 443) и заголовок вообще не показывает номер порта. Проверено с помощью nginx-extra 1.10.3. Это потому, что это обычные порты http (s) или конфигурация nginx? Этот комментарий просто говорит о том, что вещи не всегда ведут себя так, как вы думаете.

Мухаммед Нурельдин
источник
0

Я тоже некоторое время боролся с этим. Стало ясно, когда я понял, что $ http_XXXXX ссылается на все объявленные переменные заголовка.

Таким образом, $ http_user_agent, $ http_referer - это «АГЕНТ ПОЛЬЗОВАТЕЛЯ», а «REFERER» упоминаются в нижнем и нижнем слешах. Это объяснило мне, откуда взялся ад $ http_upgrade во многих примерах конфигурации NGINX.

Прочитайте его по адресу https://stackoverflow.com/questions/15414810/whats-the-difference-of-host-and-http-host-in-nginx

luison
источник