HTTP的演变史
HTTP(超文本传输协议)是万维网的基石协议。由蒂姆·伯纳斯-李(Tim Berners-Lee)和他的团队在1989-1991年间开发,HTTP经历了多次变革,保持了简单性的同时,灵活性不断增强。继续读下去,你会了解HTTP如何从一个为实验室半信任环境设计的文件交换协议,进化成支持高清图片、视频甚至3D内容的现代互联网迷宫。
万维网的诞生
1989年,蒂姆·伯纳斯-李在欧洲核子研究组织(CERN)工作时,提出构建一个基于互联网的超文本系统。最初叫“Mesh”,1990年实现时改名为“World Wide Web”。它基于现有的TCP和IP协议,包含四个核心组件:
- 超文本标记语言(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也不需要。
GET /my-page.html
响应也简单得离谱:只有文件内容本身。
<html>
一个纯文本网页
</html>
跟后续版本不同,HTTP/0.9没有HTTP头信息,只能传HTML文件。没有状态码或错误码,出问题时,会生成一个特定HTML文件,里面带上给人类看的问题描述。
HTTP/1.0 – 扩展的开端
HTTP/0.9很有限,但浏览器和服务器很快让它更灵活:
- 版本信息:每条请求带上版本号(
GET
行后加HTTP/1.0
)。 - 状态码:响应开头加上状态码行,让浏览器知道请求成功或失败,调整行为,比如更新或使用本地缓存。
- HTTP头部:请求和响应都引入头部,传输元数据,让协议变得超级灵活可扩展。
- 内容类型:通过
Content-Type
头部,可以传输非HTML文件。
这时候,典型的请求和响应长这样:
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>
带图片的页面
<img src="my-image.gif">
</html>
接着会建立第二个连接,请求图片(带对应的响应):
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
(图片内容)
1991-1995年间,这些功能是“试试看”的方式引入的。服务器或浏览器加个新功能,看看能不能火。互操作问题很常见。为了解决这些问题,1996年11月发布了一个信息性文档,描述常见做法,称为RFC 1945,定义了HTTP/1.0。
HTTP/1.1 – 标准化协议
与此同时,正式标准化也在进行,和HTTP/1.0的各种实现并行。1997年初,HTTP/1.1发布,距HTTP/1.0仅几个月。
HTTP/1.1澄清了模糊点,带来很多改进:
- 连接复用:连接可以重复使用,省去多次打开连接的时间。
- 流水线处理:可以在第一个请求的响应完全传回前发送第二个请求,降低通信延迟。
- 分块传输:支持分块响应。
- 缓存控制:引入更多缓存控制机制。
- 内容协商:包括语言、编码、类型,客户端和服务器可以协商交换的内容。
- Host头部:支持同一IP地址托管不同域名,方便服务器共存。
下面是一个HTTP/1.1请求序列的例子,展示如何通过单一持久TCP连接高效加载资源。第一个请求获取网页,服务器返回HTML文档,客户端解析HTML后,依次请求CSS和JavaScript资源:
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字节的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字节的CSS内容]
GET /static/js/main.a918a4e7.js HTTP/1.1
Host: developer.mozilla.org
…
建立TCP连接是客户端-服务器交互的昂贵部分,TCP慢启动意味着长连接比新连接快。HTTP/1.1允许复用TCP连接,省去每次请求都新建连接的麻烦。但客户端仍需等上个资源下载完才能请求下一个(队头阻塞)。为解决这问题,大多数浏览器允许每个网站(或源)最多开6个TCP连接,平行获取多个资源,大幅提升HTTP/1.1性能。
HTTP/1.1首次发布为RFC 2068,1997年1月。
二十多年的发展
HTTP的扩展性让添加新头部和方法变得简单。尽管HTTP/1.1经过两次修订(1999年6月的RFC 2616,2014年6月的RFC 7230-7235),在HTTP/2发布前,它稳定了15年以上。2022年,HTTP/1.1再次更新为RFC 9110。现在HTTP规范分为:语义(RFC 9110,适用于所有HTTP版本)、缓存(RFC 9111)、HTTP/1.1(RFC 9112)、HTTP/2(RFC 9113)、HTTP/3(RFC 9114)。此外,HTTP终于成为互联网标准(STD 97),此前一直是提议/草案标准。
用HTTP进行安全传输
1994年底,HTTP迎来最大变革。网景通信公司(Netscape)在TCP/IP之上加了加密传输层:SSL。SSL 1.0从未公开,SSL 2.0及其后续SSL 3.0为电商网站提供了加密和消息真实性保证。SSL最终标准化为TLS。
同期,加密传输层的需求变得明显。万维网不再是学术网络,而成了广告商、个人、犯罪分子争夺私人数据的丛林。随着HTTP应用需要访问地址簿、邮件、用户位置等隐私信息,TLS在电商之外也变得必要。
用HTTP构建复杂应用
蒂姆·伯纳斯-李最初没把HTTP设想为只读媒介。他想要一个支持远程添加和移动文档的网络,像分布式文件系统。1996年,HTTP扩展支持创作,诞生了WebDAV标准,扩展到CardDAV(处理地址簿)和CalDAV(处理日历)。但这些*DAV扩展有个缺点:只有服务器实现才能用。
2000年,出现了新模式:表述性状态转移(REST)。REST API不依赖新HTTP方法,而是通过标准HTTP/1.1方法访问特定URI,允许Web应用无需更新浏览器或服务器就能获取和修改数据。所有必要信息都嵌入网站通过标准HTTP/1.1提供的文件中。REST的缺点是每个网站定义自己的非标准RESTful API,完全控制它,与*DAV扩展的客户端-服务器互操作性不同。2010年代,RESTful API变得非常普遍。
2005年起,更多API为网页开放,部分扩展了HTTP协议:
- 服务器推送事件:服务器可向浏览器推送消息。
- WebSocket:通过升级现有HTTP连接建立的新协议。
放宽Web安全模型
HTTP独立于Web安全模型(同源策略)。其实,当前Web安全模型是HTTP创建后才开发的!多年来,在特定条件下放宽同源策略限制被证明很有用。服务器通过一组新HTTP头部告诉客户端何时放宽限制,定义在跨源资源共享(CORS)和内容安全策略(CSP)等规范中。
除了这些大扩展,还加了许多头部,有时只是试验性的。著名头部包括控制隐私的DNT
(不跟踪)、X-Frame-Options
和Upgrade-Insecure-Requests
等。
HTTP/2 – 性能更强的协议
网页越来越复杂,有些甚至是独立应用。显示的视觉媒体增多,增加交互性的脚本体积也变大。传输的数据量和HTTP请求数激增,给HTTP/1.1连接带来更多复杂性和开销。为解决这问题,谷歌2010年代初实现实验性协议SPDY,改进了客户端-服务器数据交换方式,吸引了浏览器和服务器开发者的兴趣。SPDY提升响应速度,解决重复数据传输问题,成为HTTP/2的基础。
HTTP/2与HTTP/1.1的区别:
- 二进制协议:不再是文本协议,无法手动读写,但支持更优的优化技术。
- 多路复用:同一连接可并行处理多个请求,消除HTTP/1.x的限制。
- 头部压缩:一组请求的头部常类似,压缩去掉重复和开销。
HTTP/2于2015年5月正式标准化,2022年1月使用率峰值达46.9%(见统计数据)。高流量网站为节省数据传输开销和预算,采用最快。
HTTP/2采用快可能因为它无需改动网站和应用。只需更新服务器和浏览器即可。随着旧版浏览器和服务器更新,使用率自然增长,开发者无需额外工作。
HTTP/2之后的演变
HTTP的扩展性仍在为新功能铺路。2016年出现了几个新扩展:
- Alt-Svc支持:允许资源标识和位置分离,支持更智能的CDN缓存机制。
- 客户端提示:浏览器或客户端可主动向服务器传递需求和硬件限制信息。
- Cookie安全前缀:保证安全Cookie不被篡改。
HTTP/3 – 基于QUIC的HTTP
HTTP/3是HTTP的下一大版本,语义与早期版本相同,但用QUIC替代TCP作为传输层。到2022年10月,26%的网站使用HTTP/3。
QUIC为HTTP连接提供更低延迟。像HTTP/2,QUIC是多路复用协议,但HTTP/2在单一TCP连接上运行,TCP层的丢包检测和重传会阻塞所有流。QUIC在UDP上运行多个流,独立为每个流处理丢包检测和重传,错误只阻塞包含数据的流。
HTTP/3定义在RFC 9114,受主流浏览器支持,包括Chromium(及其变种如Chrome、Edge)和Firefox。