Press "Enter" to skip to content

HTTP1.0下HTTP_HOST为空

昨天xuepeng师兄提出一个问题是 $_SERVER['HTTP_HOST']为空, 经过我翻看RFC文档以及测试,得出结论如下:
在http 1.1中, host字段是不能为空的,如果为空, 服务器会认为是bad request
但是在http 1.0中, host字段是可以为空的. 如:

  <?php
$fp = fsockopen("localhost", 80, $errno, $errstr, 30);
$header =  "GET /index.php";
$header .= " HTTP/1.0\r\n";
$header .= "Connection:Close\r\n\r\n";
fwrite($fp, $header);
    echo fread($fp, 1024);
fclose($fp);
?>

其中,主机的index.php只是var_dump($_SERVER['HTTP_HOST']);
可以看到,当你指明使用http 1.0协议的时候, 请求正常,返回结果是false;
但是如果你指明协议是http 1.1 :

<?php
$fp = fsockopen("localhost", 80, $errno, $errstr, 30);
$header =  "GET /index.php";
$header .= " HTTP/1.1\r\n";
$header .= "Connection:Close\r\n\r\n";
fwrite($fp, $header);
    echo fread($fp, 1024);
fclose($fp);
?>

则结果是400 bad request;
究其原因是因为在HTTP1.0的时候, 并没有设想到现在有这么多服务器共用一个IP的情况(virtual host), 而在HTTP1.1的时候,加入了对多个HOST共用一个IP的支持.
以下文字摘自RFC2616:

14.23 Host
The Host request-header field specifies the Internet host and port
number of the resource being requested, as obtained from the original
URI given by the user or referring resource (generally an HTTP URL,
Fielding, et al. Standards Track [Page 128]

RFC 2616 HTTP/1.1 June 1999
as described in section 3.2.2). The Host field value MUST represent
the naming authority of the origin server or gateway given by the
original URL. This allows the origin server or gateway to
differentiate between internally-ambiguous URLs, such as the root "/"
URL of a server for multiple host names on a single IP address.
Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
A "host" without any trailing port information implies the default
port for the service requested (e.g., "80" for an HTTP URL). For
example, a request on the origin server for
would properly include:
GET /pub/WWW/ HTTP/1.1
Host: www.w3.org
A client MUST include a Host header field in all HTTP/1.1 request
messages . If the requested URI does not include an Internet host
name for the service being requested, then the Host header field MUST
be given with an empty value. An HTTP/1.1 proxy MUST ensure that any
request message it forwards does contain an appropriate Host header
field that identifies the service being requested by the proxy. All
Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request)
status code to any HTTP/1.1 request message which lacks a Host header
field.

以下省略.....

后记: 虽然HTTP_HOST不能缺失, 但是可以为空值 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23):

If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value.

Be First to Comment

  1. JackZhouMine
    JackZhouMine May 14, 2019

    请教一下。
    为什么我在chrome和firefox的网络面板里,没有看到这个HOST字段呢?chrome 的general ,里面有一个字段 Remote Address,值是一个ip:port,请问这个字段和host有什么不同呢?

  2. LungZeno
    LungZeno May 10, 2009

    HOST 欄位通常用於實現 name-based 虛擬主機。
    HOST 欄位儲存了你在瀏覽器發請求時,完整 URL 中的域名(或 IP 地址)與連接埠(port,如果有的話),網路上封包的傳輸是使用 IP 地址,與域名無關,因此才有 DNS ,在發封包前先由域名 lookup 出 IP 地址,而伺服器軟體和客戶端軟體接收封包是依靠 IP 地址和 port (TCP port 或 UDP port),也是與域名無關,你使用一些設定或工具,host name是可以任意填寫的(攻擊?),只要分開指定 IP 地址和 port 就可以,不一定要用那 host name 對應的 IP 地址和 port , HTTP Proxy 就是這樣實現的。

    • LungZeno
      LungZeno May 10, 2009

      我的句子有歧義,「只要分開指定 IP 地址和 port 就可以」是指「只要分開 host name 的指定與 IP 地址和 port 的指定就可以」。

    • 雪候鸟
      雪候鸟 May 10, 2009

      你是台湾的? 都是繁体, 并且用词也不太一样, 呵呵

      • LungZeno
        LungZeno May 11, 2009

        我是刻意的,因為實質情況是這樣:
        平常溝通和工作,對於 IT 術語,人們使用純英文而不使用中文,甚至不知道對應的中文說法,或根本沒有對應的中文說法,等的嚴重程度為:
        香港>台灣>大陸
        在這個網路時代,大家都透過網路學習,加上大陸的人口遠多過港台,很多轉載文章都使用劣拙的繁簡轉換,因而很多台灣年青人都在使用大陸 IT 中文術語,除非他們在之前已在學校學到台灣版本,但教師也會透過網路學習……更不說極多香港人根本不懂分辨甚或不屑分辨。
        我堅持,其中一個原因是因為語文常是學習、理解、溝通的第一通關口。

        • LungZeno
          LungZeno May 11, 2009

          錯別字:
          第一通關口→第一度關口

        • LungZeno
          LungZeno May 11, 2009

          錯別字:
          第一度關口→第一道關口

  3. migou
    migou November 24, 2008

    请教一下HTTP的HOST字段与DNS有什么区别和联系呢?

    • 雪候鸟
      雪候鸟 November 24, 2008

      HOST指明了要访问的主机名, DNS不知道你是指什么,是指服务器的域名么?

Comments are closed.