HTTP 的演变

HTTP (超文本传输协议) 是万维网的基础协议。由蒂姆·伯纳斯-李和他的团队在 1989 年至 1991 年间开发,HTTP 经历了许多变化,这些变化在保持其简单性的同时,也塑造了其灵活性。继续阅读,了解 HTTP 如何从一个旨在在半信任实验室环境中交换文件的协议,演变为一个承载高清图像和视频以及 3D 内容的现代互联网迷宫。

万维网的发明

1989 年,蒂姆·伯纳斯-李在 CERN 工作期间,撰写了一份关于在互联网上构建超文本系统的提案。最初称为 Mesh,在 1990 年实现时,它被重新命名为 World Wide Web。它建立在现有的 TCP 和 IP 协议之上,由 4 个构建模块组成:

  • 一种表示超文本文档的文本格式,即 超文本标记语言 (HTML)。
  • 一种用于交换这些文档的协议,即 超文本传输协议 (HTTP)。
  • 一个用于显示(和编辑)这些文档的客户端,第一个网络浏览器名为 WorldWideWeb
  • 一个用于访问文档的服务器,即 httpd 的早期版本。

这四个构建模块在 1990 年底完成,第一批服务器在 1991 年初在 CERN 之外运行。1991 年 8 月 6 日,蒂姆·伯纳斯-李在公共新闻组 alt.hypertext 发表了一篇帖子。这现在被认为是万维网作为一个公共项目的正式开始。

早期阶段使用的 HTTP 协议非常简单。它后来被称为 HTTP/0.9,有时也被称为单行协议。

HTTP/0.9 – 单行协议

HTTP 的初始版本没有版本号;它后来被称为 0.9,以区别于后续版本。HTTP/0.9 极其简单:请求只由一行组成,以唯一的可能方法 GET 开头,后跟资源的路径。完整的 URL 没有包含在内,因为一旦连接到服务器,协议、服务器和端口就不再是必需的。

http
GET /my-page.html

响应也极其简单:它只包含文件本身。

html
<html>
  An text-only web page
</html>

与后续演变不同,没有 HTTP 头。这意味着只能传输 HTML 文件。没有状态码或错误码。如果出现问题,会生成一个特定的 HTML 文件,其中包含问题的描述供人类阅读。

HTTP/1.0 – 构建可扩展性

HTTP/0.9 非常有限,但浏览器和服务器很快使其更加通用。

  • 版本信息随每个请求发送(HTTP/1.0 附加到 GET 行)。
  • 响应开始时还会发送一个状态码行。这允许浏览器自身识别请求的成功或失败,并相应地调整其行为。例如,以特定方式更新或使用其本地缓存。
  • HTTP 头的概念被引入到请求和响应中。元数据可以传输,协议变得极其灵活和可扩展。
  • 由于 Content-Type 头,除了纯 HTML 文件之外的文档也可以传输。

此时,典型的请求和响应如下所示:

http
GET /my-page.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

HTTP/1.0 200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
A page with an image
  <IMG SRC="/my-image.gif">
</HTML>

紧接着是第二次连接和获取图像的请求(以及相应的响应):

http
GET /my-image.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

HTTP/1.0 200 OK
Date: Tue, 15 Nov 1994 08:12:32 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/gif
(image content)

在 1991 年至 1995 年间,这些是采用试探性方法引入的。服务器和浏览器会添加一个功能,并查看它是否受到欢迎。互操作性问题很常见。为了解决这些问题,1996 年 11 月发布了一份描述常见做法的信息性文档。这被称为 RFC 1945,并定义了 HTTP/1.0。

HTTP/1.1 – 标准化协议

与此同时,适当的标准化正在进行中。这与 HTTP/1.0 的各种实现并行进行。HTTP 的第一个标准化版本 HTTP/1.1 于 1997 年初发布,仅比 HTTP/1.0 晚几个月。

HTTP/1.1 澄清了歧义并引入了许多改进:

  • 连接可以重用,这节省了时间。它不再需要多次打开以显示单个原始文档中嵌入的资源。
  • 添加了管道化。这允许在第一个请求的响应完全传输之前发送第二个请求。这降低了通信延迟。
  • 也支持分块响应。
  • 引入了额外的缓存控制机制。
  • 引入了内容协商,包括语言、编码和类型。客户端和服务器现在可以就交换哪些内容达成一致。
  • 由于 Host 头,从同一 IP 地址托管不同域的能力允许服务器托管。

以下示例说明了通过单个持久 TCP 连接发送的 HTTP/1.1 请求的典型序列,演示了客户端如何重用连接以更有效地加载资源。第一个请求检索一个网页,服务器响应一个 HTML 文档。客户端随后会随着在 HTML 中遇到 CSS 和 JavaScript 资源而顺序发送额外的请求。

http
GET /en-US/docs/ HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive

HTTP/1.1 200 OK
accept-ranges: none
content-encoding: br
date: Tue, 01 Jul 2025 08:32:50 GMT
expires: Tue, 01 Jul 2025 09:26:50 GMT
cache-control: public, max-age=3600
age: 1926
last-modified: Sat, 28 Jun 2025 00:47:12 GMT
etag: W/"b55394ed2f274eea5d528cf6c91e1dcf"
content-type: text/html
vary: Accept-Encoding
content-length: 26178

[26178 bytes of HTML]

GET /static/css/main.9e7d1ce5.css HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/css,*/*;q=0.1
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd

HTTP/1.1 200 OK
content-encoding: br
content-length: 43694
date: Mon, 30 Jun 2025 21:13:12 GMT
expires: Mon, 30 Jun 2025 21:47:29 GMT
cache-control: public, max-age=31536000
age: 42704
last-modified: Mon, 30 Jun 2025 00:33:45 GMT
etag: W/"d4f4d0955482844ad842986a9bcb7e8a"
content-type: text/css
vary: Accept-Encoding

[43694 bytes of CSS]

GET /static/js/main.a918a4e7.js HTTP/1.1
Host: developer.mozilla.org
…

建立 TCP 连接是客户端-服务器交换中成本高昂的一部分,而 TCP 慢启动 意味着寿命更长的连接比新创建的连接更快。HTTP/1.1 允许您为多个请求和响应重用一个 TCP 连接,从而避免为每个请求创建新连接。然而,客户端仍然必须等待每个资源下载完毕才能请求下一个资源(队头阻塞)。为了解决这个问题,大多数浏览器允许每个网站(或)最多有六个 TCP 连接。通过六个并行连接,浏览器可以使用 HTTP/1.1 模型同时获取多个资源,这显著提高了性能。

HTTP/1.1 最初于 1997 年 1 月作为 RFC 2068 发布。

二十多年的发展

HTTP 的可扩展性使得创建新的头和方法变得容易。尽管 HTTP/1.1 协议在两次修订中得到了完善,即 1999 年 6 月发布的 RFC 2616 和在 HTTP/2 发布之前于 2014 年 6 月发布的 RFC 7230-RFC 7235,但它在 15 年多的时间里一直非常稳定。HTTP/1.1 在 2022 年通过 RFC 9110 再次更新。HTTP 不仅更新了,而且所有的 HTTP 都被修订,现在分为以下文档:语义 (RFC 9110)、缓存 (RFC 9111) 适用于所有 HTTP 版本,以及 HTTP/1.1 (RFC 9112)、HTTP/2 (RFC 9113) 和 HTTP/3 (RFC 9114)。此外,该规范最终达到了互联网标准 (STD 97) 的地位,而在此之前它一直是一个提议/草案标准。

使用 HTTP 进行安全传输

HTTP 的最大变化发生在 1994 年底。计算机服务公司 Netscape Communications 没有在基本的 TCP/IP 栈上发送 HTTP,而是在其之上创建了一个额外的加密传输层:SSL。SSL 1.0 从未向公众发布,但 SSL 2.0 及其后续版本 SSL 3.0 允许创建电子商务网站。为此,它们加密并保证了服务器和客户端之间交换消息的真实性。SSL 最终被标准化并成为 TLS。

在同一时期,加密传输层的重要性变得显而易见。网络不再是一个主要由学术机构组成的网络,而是变成了一个广告商、随机个人和犯罪分子争夺尽可能多私人数据的“丛林”。随着基于 HTTP 构建的应用程序变得更加强大,并需要访问私人信息,如地址簿、电子邮件和用户位置,TLS 在电子商务用例之外也变得必要。

将 HTTP 用于复杂应用程序

蒂姆·伯纳斯-李最初并未将 HTTP 设想为只读媒体。他希望创建一个人们可以在远程添加和移动文档的网络——一种分布式文件系统。大约在 1996 年,HTTP 被扩展以允许创作,并创建了一个名为 WebDAV 的标准。它发展到包括特定应用程序,如用于处理地址簿条目的 CardDAV 和用于处理日历的 CalDAV。但所有这些 *DAV 扩展都有一个缺陷:它们只有在服务器实现时才可用。

2000 年,设计了一种使用 HTTP 的新模式:表述性状态转移(或 REST)。API 不基于新的 HTTP 方法,而是依赖于使用基本的 HTTP/1.1 方法访问特定的 URI。这允许任何 Web 应用程序通过 API 检索和修改其数据,而无需更新浏览器或服务器。所有必要的信息都嵌入在网站通过标准 HTTP/1.1 提供的文件中。REST 模型的缺点是每个网站都定义了自己的非标准 RESTful API 并对其拥有完全控制权。这与客户端和服务器可以互操作的 *DAV 扩展不同。RESTful API 在 2010 年代变得非常普遍。

自 2005 年以来,更多的 API 可用于网页。其中一些 API 为特定目的创建了 HTTP 协议的扩展:

  • 服务器发送事件,服务器可以将偶尔的消息推送到浏览器。
  • WebSocket,一种可以通过升级现有 HTTP 连接来设置的新协议。

放宽 Web 的安全模型

HTTP 独立于 Web 安全模型,即 同源策略。事实上,当前的 Web 安全模型是在 HTTP 创建之后才发展起来的!多年来,在某些限制下解除该策略的一些限制被证明是有用的。服务器使用一组新的 HTTP 头将解除这些限制的程度和时间传输给客户端。这些在 跨域资源共享 (CORS) 和 内容安全策略 (CSP) 等规范中定义。

除了这些大型扩展之外,还添加了许多其他头,有时只是实验性的。值得注意的头包括用于控制隐私的 Do Not Track (DNT) 头、X-Frame-OptionsUpgrade-Insecure-Requests,但还有更多。

HTTP/2 – 更高性能的协议

多年来,网页变得越来越复杂。其中一些甚至本身就是应用程序。显示了更多的视觉媒体,增加交互性的脚本的数量和大小也增加了。通过更多的 HTTP 请求传输了更多的数据,这给 HTTP/1.1 连接带来了更多的复杂性和开销。为了解决这个问题,Google 在 2010 年代早期实施了一个实验性协议 SPDY。这种客户端和服务器之间交换数据的替代方式吸引了浏览器和服务器开发人员的兴趣。SPDY 定义了响应能力的提高,并解决了重复数据传输的问题,为 HTTP/2 协议奠定了基础。

HTTP/2 协议与 HTTP/1.1 有以下几点不同:

  • 它是一个二进制协议而不是文本协议。它不能手动读取和创建。尽管有这个障碍,它允许实施改进的优化技术。
  • 它是一个多路复用协议。可以在同一连接上进行并行请求,消除了 HTTP/1.x 协议的限制。
  • 它压缩头。由于这些头在一组请求中通常相似,这消除了数据传输的重复和开销。

HTTP/2 于 2015 年 5 月正式标准化,其使用率在 2022 年 1 月达到峰值,占所有网站的 46.9%(请参阅这些统计数据)。高流量网站为了节省数据传输开销和随后的预算,表现出最快的采用速度。

这种快速采用很可能是因为 HTTP/2 不需要更改网站和应用程序。要使用它,只需要一个与最新浏览器通信的最新服务器。只需要有限的群体来推动采用,随着旧版浏览器和服务器的更新,使用率自然会增加,而无需 Web 开发人员进行大量工作。

HTTP/2 之后的演变

HTTP 的可扩展性仍在用于添加新功能。值得注意的是,我们可以引用 2016 年出现的 HTTP 协议新扩展:

  • Alt-Svc 的支持允许将给定资源的标识与位置分离。这意味着更智能的 CDN 缓存机制。
  • 引入 客户端提示 允许浏览器或客户端主动将其要求和硬件限制信息传达给服务器。
  • Cookie 头中引入安全相关前缀有助于保证安全 cookie 不会被篡改。

HTTP/3 - 基于 QUIC 的 HTTP

HTTP 的下一个主要版本 HTTP/3 与早期版本的 HTTP 具有相同的语义,但传输层部分使用 QUIC 而不是 TCP。截至 2022 年 10 月,所有网站的 26% 都在使用 HTTP/3

QUIC 旨在为 HTTP 连接提供更低的延迟。像 HTTP/2 一样,它是一个多路复用协议,但 HTTP/2 运行在单个 TCP 连接上,因此在 TCP 层处理的丢包检测和重传可能会阻塞所有流。QUIC 在 UDP 上运行多个流,并为每个流独立实现丢包检测和重传,因此如果发生错误,只有包含该数据包的流会被阻塞。

RFC 9114 中定义,HTTP/3 受到大多数主流浏览器的支持,包括 Chromium(及其变体,如 Chrome 和 Edge)和 Firefox。

另见