$_SERVER['HTTP_HOST']和$_SERVER['SERVER_NAME']在PHP中的区别是什么?
什么时候你会考虑使用其中一种而不是另一种,为什么?
$_SERVER['HTTP_HOST']和$_SERVER['SERVER_NAME']在PHP中的区别是什么?
什么时候你会考虑使用其中一种而不是另一种,为什么?
当前回答
我花了一段时间才理解人们所说的“SERVER_NAME更可靠”是什么意思。我使用共享服务器,不能访问虚拟主机指令。因此,我在.htaccess中使用mod_rewrite来将不同的HTTP_HOSTs映射到不同的目录。在这种情况下,HTTP_HOST是有意义的。
The situation is similar if one uses name-based virtual hosts: the ServerName directive within a virtual host simply says which hostname will be mapped to this virtual host. The bottom line is that, in both cases, the hostname provided by the client during the request (HTTP_HOST), must be matched with a name within the server, which is itself mapped to a directory. Whether the mapping is done with virtual host directives or with htaccess mod_rewrite rules is secondary here. In these cases, HTTP_HOST will be the same as SERVER_NAME. I am glad that Apache is configured that way.
但是,基于ip的虚拟主机的情况有所不同。在这种情况下,且仅在这种情况下,SERVER_NAME和HTTP_HOST可以是不同的,因为现在客户端通过IP而不是名称来选择服务器。确实,在某些特殊的构型中这很重要。
因此,从现在开始,我将使用SERVER_NAME,以防我的代码移植到这些特殊配置中。
其他回答
如果你想检查server.php或其他什么,你想用下面的方法调用它:
<?php
phpinfo(INFO_VARIABLES);
?>
or
<?php
header("Content-type: text/plain");
print_r($_SERVER);
?>
然后使用您站点的所有有效url访问它,并检查差异。
正如我在回答中提到的,如果服务器运行在不是80的端口上(在开发/intranet机器上可能很常见),那么HTTP_HOST包含端口,而SERVER_NAME不包含端口。
$_SERVER['HTTP_HOST'] == 'localhost:8080'
$_SERVER['SERVER_NAME'] == 'localhost'
(至少这是我在Apache基于端口的虚拟主机中注意到的)
注意在HTTPS上运行时HTTP_HOST不包含:443(除非您在非标准端口上运行,我没有测试过)。
正如其他人所指出的,这两者在使用IPv6时也有所不同:
$_SERVER['HTTP_HOST'] == '[::1]'
$_SERVER['SERVER_NAME'] == '::1'
假设你有一个简单的设置(CentOS 7, Apache 2.4。x和PHP 5.6.20),只有一个网站(不假设虚拟主机)…
在PHP的意义上,$_SERVER['SERVER_NAME']是PHP在$_SERVER超全局中注册的一个元素,基于httpd.conf中的Apache配置(**ServerName** directive with UseCanonicalName on)(可能来自包含的虚拟主机配置文件,等等…)HTTP_HOST派生自HTTP主机头。将其视为用户输入。使用前进行筛选和验证。
下面是一个例子,我使用$_SERVER['SERVER_NAME']作为比较的基础。下面的方法来自我创建的名为ServerValidator (Validator的子类)的具体子类。ServerValidator在使用$_SERVER中的6或7个元素之前检查它们。
在确定HTTP请求是否是POST时,我使用了这个方法。
public function isPOST()
{
return (($this->requestMethod === 'POST') && // Ignore
$this->hasTokenTimeLeft() && // Ignore
$this->hasSameGETandPOSTIdentities() && // Ingore
($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')));
}
在调用此方法时,所有相关$_SERVER元素的过滤和验证(以及相关属性的设置)都已经完成。
台词……
($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')
... 检查$_SERVER['HTTP_HOST']值(最终从请求的主机HTTP报头派生)是否与$_SERVER['SERVER_NAME']匹配。
现在,我使用超全局语言来解释我的示例,但这只是因为有些人不熟悉关于filter_input_array()的INPUT_GET、INPUT_POST和INPUT_SERVER。
The bottom line is, I do not handle POST requests on my server unless all four conditions are met. Hence, in terms of POST requests, failure to provide an HTTP host header (presence tested for earlier) spells doom for strict HTTP 1.0 browsers. Moreover, the requested host must match the value for ServerName in the httpd.conf, and, by extention, the value for $_SERVER('SERVER_NAME') in the $_SERVER superglobal. Again, I would be using INPUT_SERVER with the PHP filter functions, but you catch my drift.
请记住,Apache经常在标准重定向中使用ServerName(例如,将URL后面的斜杠去掉:例如,http://www.example.com变成http://www.example.com/),即使您没有使用URL重写。
我使用$_SERVER['SERVER_NAME']作为标准,而不是$_SERVER['HTTP_HOST']。在这个问题上有很多争论。$_SERVER['HTTP_HOST']可以是空的,所以这不应该是创建代码约定的基础,比如我上面的公共方法。但是,仅仅因为它们都是集合并不能保证它们是相等的。测试是最好的方法(记住Apache版本和PHP版本)。
$_SERVER['SERVER_NAME']基于您的web服务器配置。 $_SERVER['HTTP_HOST']是基于来自客户端的请求。
看我想知道什么了。SERVER_NAME是服务器的主机名,而HTTP_HOST是客户端连接到的虚拟主机。