Это сервер Ubuntu, на котором запущен PHP 7 на Apache, с веб-сайтом, который применяет TLS (с использованием стандартного порта). Насколько я понимаю, https://example.com
и https://example.com:443
точно эквивалентны (и действительно, в моем браузере номер порта исчезает из адресной строки, когда я его ввожу). И все же HTTP_HOST
обычно содержит только доменное имя, но иногда содержит также номер порта. это мог быть для посетителей-ботов (логи я не анализировал), но даже в этом случае не понимаю, как. Есть ли реальная разница?
(Это вызывает некоторые проблемы, поскольку некоторые из наших журналов, рабочих очередей и кеша на стороне сервера разделены HTTP_HOST
, поэтому наличие одного и того же отчета на разных хостах сбивает с толку.)
В Документация PHP утверждает, что $_SERVER['HTTP_HOST']
является:
Содержание Хост: заголовок из текущего запроса, если он есть.
Действительно, каждая переменная в этом ассоциативном массиве, ключ которой начинается со строки HTTP_
- это копия соответствующей переменной HTTP-запроса, отправленная пользовательским агентом.
Итак, почему он иногда содержит имя хоста, а иногда и имя хоста, и номер порта?
Оказывается, оба синтаксиса допустимы и эквивалентны. Номер порта требуется, если сервер использует порт, отличный от порта по умолчанию, в противном случае - необязательный.
При каких обстоятельствах пользовательский агент будет отправлять номер порта, даже если он установлен по умолчанию?
RFC 7230 раздел 5.4 объясняет, что значение заголовка Host: является точной копией авторитетного компонента URI.
Если целевой URI включает в себя компонент полномочий, то клиент ДОЛЖЕН отправить значение поля для Host, которое идентично этому компоненту полномочий, за исключением подкомпонента userinfo и его разделителя «@». . .
Что такое авторитетная составляющая?
Это происходит из определения URI в RFC 3986 раздел 3.2, что объясняет, что это информация о пользователе (имя пользователя и пароль), хост и порт. В нем объясняется, что порт СЛЕДУЕТ опускать, если он является портом по умолчанию, но СЛЕДУЕТ не равно ДОЛЖЕН. (Видеть RFC 2119.)
Итак, чтобы собрать все это вместе, ожидается, что пользовательский агент отправит номер порта в заголовке Host :, если он также присутствует в URI. Таким образом, если пользовательский агент имеет URL https://example.com:443/robots.txt
тогда у него будет заголовок Host: example.com:443
. Невозможно сказать, как пользовательский агент получил такой URL. Он мог быть отправлен вашим приложением или создан пользовательским агентом.
RFC 7230 раздел 2.7.3 объясняет нормализацию URL-адресов, которая в данном случае означает, что URL-адрес, не содержащий номера порта, и URL-адрес, содержащий номер порта по умолчанию, эквивалентны.
TL; DR: ваше приложение должно ожидать, что номер порта может появиться в этом заголовке, и обрабатывать его каким-либо образом, соответствующим контексту, в котором он используется.
Вместо этого вы можете использовать $_SERVER['SERVER_NAME']
, который содержит значение ServerName
директива в Apache <VirtualHost>
который обработал запрос (или, для nginx, первый server_name
в server
блок).