鉴于发送 HTTP 请求时 TCP 连接已经建立,IP 地址和端口是隐式已知的——TCP 连接是 IP + 端口。
那么,为什么我们需要Host标题呢?这是否仅在有多个主机映射到 TCP 连接中隐含的 IP 地址的情况下才需要?
Host
标Host头告诉网络服务器要使用哪个 虚拟主机 (如果已设置)。您甚至可以使用多个 别名 (= 域和通配符域)拥有相同的虚拟主机。在这种情况下,如果您想根据寻址的不同域提供不同的行为,您仍然可以在 Web 应用程序中手动读取该标头。这是可能的,因为在您的网络服务器中,您可以(如果我没记错的话,您必须)设置 一个 虚拟主机作为默认主机。host只要标头与任何配置的虚拟主机不匹配,就会使用此默认虚拟主机。
host
这意味着:您说得对,尽管说“多个主机”可能会有些误导:主机(寻址的机器)是相同的,真正解析为 IP 地址的是也被引用的不同 域名 (包括子域)作为 主机名 (但不是主机!)。
虽然不是问题的一部分,但有一个有趣的事实:该规范在早期导致 SSL 出现问题,因为 Web 服务器必须交付与客户端处理的域相对应的证书。但是,为了知道使用什么证书,网络服务器应该事先知道寻址的主机名。但是由于客户端仅通过加密通道发送该信息(这意味着:在证书已经发送之后),服务器必须假设您浏览了默认主机。这意味着每个 IP 地址/端口组合有一个 SSL 安全域。
服务器名称指示已经克服了这一点;但是,这再次破坏了一些隐私,因为服务器名称现在再次以纯文本传输,因此每个中间人都会看到您尝试连接的 主机名。
虽然网络服务器会从服务器名称指示中知道主机名,但Host标头并没有过时,因为服务器名称指示信息仅在 TLS 握手中使用。对于不安全的连接,根本没有服务器名称指示,因此Host标头仍然有效(并且是必要的)。
另一个有趣的事实:大多数网络服务器(如果不是全部)拒绝您的 HTTP 请求,如果它不包含确切的一个Host标头,即使它可以被省略,因为只配置了默认 vhost。这意味着 http-(get-) 请求中所需的最少信息是包含METHOD RESOURCE并且PROTOCOL VERSION至少是Host标题的第一行,如下所示:
METHOD
RESOURCE
PROTOCOL VERSION
GET /someresource.html HTTP/1.1 Host: www.example.com
在“主机”标题的 MDN 文档中,他们实际上是这样表述的:
必须在所有 HTTP/1.1 请求消息中发送 Host 标头字段。400(错误请求)状态代码将被发送到任何缺少主机头字段或包含多个头字段的 HTTP/1.1 请求消息。
正如 Darrel Miller 所提到的,完整的规范可以在RFC7230中找到。