这是一个在 Apache 上运行 PHP 7 的 Ubuntu 服务器,其网站强制执行 TLS(使用标准端口)。据我了解,https://example.com
并且https://example.com:443
完全等效(实际上,在我的浏览器中,当我输入端口号时,端口号会从地址栏中消失)。然而,HTTP_HOST
通常只包含域名,但有时还包含端口号。这可能适用于机器人访问者(我没有分析日志),但即便如此我也不知道如何。有什么实际区别吗?
(这会导致一些问题,因为我们的一些日志和工作队列以及服务器端缓存是用 分隔的HTTP_HOST
,所以在不同的主机上拥有相同的站点报告会令人困惑。)
PHP
$_SERVER['HTTP_HOST']
文档指出:事实上,在这个关联数组中,其键以字符串开头的每个变量都是
HTTP_
用户代理发送的相应 HTTP 请求变量的副本。那么,为什么它有时包含主机名,有时又包含主机名和端口号呢?
事实证明,这两种语法都是合法且等效的。如果服务器使用非默认端口,则端口号是必需的,否则是可选的。
在什么情况下,即使是默认端口号,用户代理也会发送端口号?
RFC 7230 第 5.4 节解释说 Host: 标头的值是 URI 权限组件的精确副本。
什么是权限组件?
这来自RFC 3986 第 3.2 节中对 URI 的定义,其中解释了它是用户信息(用户名和密码)、主机和端口。它解释了如果端口是默认端口,则应该省略该端口,但应该不等于必须。(参见RFC 2119。)
因此,总而言之,如果端口号也出现在 URI 中,用户代理应该在 Host: 标头中发送端口号。因此,如果用户代理有 URL
https://example.com:443/robots.txt
,那么它将有一个 headerHost: example.com:443
。用户代理是如何获得这样一个 URL 的,没有真正的方法可以说明。它可能是由您的应用程序发送的,也可能是由用户代理构建的。RFC 7230 第 2.7.3 节解释了 URL 规范化,在这种情况下,它表示不包含端口号的 URL 和包含默认端口号的 URL 是等效的。
TL;DR:您的应用程序必须期望端口号可能出现在此标头中,并以适合使用它的上下文的某种方式处理它。
您可以考虑改用
$_SERVER['SERVER_NAME']
,它包含处理请求ServerName
的 Apache 中指令的值<VirtualHost>
(或者,对于 nginx,块server_name
中的第一个server
)。