为什么 $_SERVER['HTTP_HOST'] 有时是 example.com,有时是 example.com:443?

为什么 $_SERVER['HTTP_HOST'] 有时是 example.com,有时是 example.com:443?

这是一台在 Apache 上运行 PHP 7 的 Ubuntu 服务器,其网站强制使用 TLS(使用标准端口)。据我所知,https://example.comhttps://example.com:443完全等同(事实上,在我的浏览器中,当我输入端口号时,端口号会从地址栏中消失)。然而HTTP_HOST 通常仅包含域名,但有时还包含端口号。这可以适用于机器人访问者(我还没有分析日志),但即便如此,我也不知道如何。有什么实际区别吗?

(这会导致一些问题,因为我们的一些日志和工作队列以及服务器端缓存被分开HTTP_HOST,因此在不同的主机上有相同的站点报告会造成混淆。)

答案1

PHP 文档指出$_SERVER['HTTP_HOST']

内容主持人:当前请求的标头(如果有)。

实际上,此关联数组中每个以字符串开头的键的变量HTTP_都是用户代理发送的相应 HTTP 请求变量的副本。

那么,为什么它有时包含主机名,有时又包含主机名和端口号?

事实证明,这两种语法都是合法且等效的。如果服务器使用非默认端口,则端口号是必需的,否则是可选的。

在什么情况下用户代理会发送端口号,即使它是默认端口号?

RFC 7230 第 5.4 节解释 Host:标头的值是 URI 的权威组件的精确副本。

如果目标 URI 包含权威组件,则客户端必须发送与该权威组件相同的主机字段值,但不包括任何用户信息子组件及其“@”分隔符……

权威成分是什么?

这来自于 URI 的定义RFC 3986 第 3.2 节,解释了它是用户信息(用户名和密码)、主机和端口。它解释了如果是默认端口,则应该省略端口,但应该不等于必须。(请参阅RFC 2119

因此,综上所述,如果端口号也出现在 URI 中,则用户代理应在 Host: 标头中发送该端口号。因此,如果用户代理有 URL,https://example.com:443/robots.txt则它将有一个标头Host: example.com:443。用户代理如何获得这样的 URL,目前还无法得知。它可能是由您的应用程序发送的,也可能是由用户代理构建的。

RFC 7230 第 2.7.3 节解释 URL 规范化,在这种情况下,表示不包含端口号的 URL 和包含默认端口号的 URL 是等效的。


TL;DR:您的应用程序必须预期端口号可能出现在此标头中,并以适合其使用上下文的某种方式处理它。

您可以考虑使用,它包含处理请求的Apache 中的指令$_SERVER['SERVER_NAME']的值(或者,对于 nginx,是块中的第一个指令)。ServerName<VirtualHost>server_nameserver

相关内容