HTTP 协议入门

2024-08-22 pv

HTTP 协议作为互联网的基石(这么说应该不为过),有着复杂且丰富的含义。

完全够写一本书了。《HTTP 权威指南》这本书大概有 720 页。

不过今天这篇文章,不打算深入聊细节,因为绝大多数内容对于普通开发者而言并不重要。如果真的有兴趣,可以去看 RFC 2616 - Hypertext Transfer Protocol — HTTP/1.1🔗

本文只是一个概述。简单讲讲 HTTP 的前世今生,产生的背景,待解决的问题,以及解决思路。

1. HTTP 概念

HTTP,即超文本传输协议(HyperText Transfer Protocol),是一个应用层协议(Application Layer Protocols)。

所谓应用层,就是直接面向用户,与用户使用的产品息息相关。

HTTP 针对的应用,是浏览器和网页服务器(后面简称服务器)。

HTTP 是 蒂姆·伯纳斯-李🔗 蒂姆·伯纳斯-李 1989 年在欧洲核子研究组织(CERN)发起,当初的设计是用来发布和接收 HTML 页面。当然今天它的使用范围被大大地拓宽了,不仅是 HTML,像 CSS,JavaScript 或者其他多媒体资源都可以基于 HTTP 实现传输。常见的,RESTful (表现层状态转换)设计风格,也是完全基于 HTTP 的。

维基百科上,HTTP 的设计目标十分简洁:

用于分布式、协作式和超媒体信息系统。

看上去十分拗口。

那么回到故事开始的地方。

当初伯纳斯-李爵士开发 HTTP 协议,是为了传输 HTML,HTML 是一种超文本标记语言(HyperText Markup Language)。这种语言起初是用于共享文档

这是一个非常重要,且十分常见的场景。

  • 分布式意味着,每个人都可以访问到内容,而且相互独立,互不干扰
  • 协作式意味着每个人的工作内容都可以发布,从而让其他人都看到
  • 超媒体信息系统,就是共享的内容,不单是文本,也可以是图片、语音,甚至视频等

于是,一种浏览器/服务器(C/S)架构被设计出来。

服务器是中心化的,所有浏览器都需要与它通信,传输的内容是 HTML。

通信协议,就是 HTTP。

距今(2024 年),HTTP 已经演进出 5 个版本

  • HTTP/0.9,已经废弃
  • HTTP/1.0,第一个在通信中指定版本号的 HTTP 协议版本
  • HTTP/1.1,优化上一个版本,使用广泛
  • HTTP/2,当前版本,于 2015 年 5 月作为互联网标准正式发布
  • HTTP/3,最新版本,于 2022 年 6 月 6 日标准化,通过 UDP 使用 QUIC 协议传输(可见,HTTP 并非与 TCP 绑定,只要能实现可靠传输,并不限制传输层协议)

不同版本的网络流量,Cloudflare Radar🔗 上有统计。

2. HTTP 工作原理

HTTP 本质是一组协议(Protocol),所谓协议,就是通信双方约定好的一种沟通手段。

语言,文字,都可以理解为一种协议。

只不过,HTTP 是用于浏览器和服务器之间交流的。

传输的内容并不复杂,就是一大段有结构的文本,分为 header 和 body 两部分。header 里放的是 body 的描述信息。

比如,使用 curl 查看本网站:

Terminal window
$ curl -I https://plantree.me
HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 82299
Cache-Control: public,max-age=0,must-revalidate
Cache-Status: "Netlify Edge"; hit
Content-Length: 23593
Content-Type: text/html; charset=UTF-8
Date: Thu, 22 Aug 2024 08:08:35 GMT
Server: Netlify

所以,HTTP 的通信内容是自解释的。看 header,很清楚地知道内容是什么。

由于 HTTP 本身是明文传输,传输的安全性,依赖底层的传输层协议,因此从这个角度看,HTTP 相当精简。这也符合计算机网络中的分层设计理念:每一层的协议,只需要做好当前层该做的。

2.1 通信主体

HTTP 的通信双方,是浏览器和服务器。

服务器是中心化的。虽然有时为了保证服务高可用,会采用冗余部署,但从用户视角看,服务器只有一个。服务器的最大作用,就是存储和响应用户的资源请求。每个资源都有一个唯一标识,叫做统一资源标识符(Uniform Resource Identifiers,URI)。

浏览器是分布式的,每个用户都可以通过浏览器,访问,甚至修改服务器上的资源。

2.2 协议内容

一次 HTTP 请求,包含两个部分:Request(请求)和 Response(响应)。

请求的内容包含:

  • 请求行
  • 请求头
  • 空行
  • 其他消息体

响应的内容包含:

  • 状态行
  • 响应头
  • 空行
  • 响应体

结构很清楚。

请求行和状态行都只有一行,是对行为的极简概述。请求头和响应头则涵盖更细节的描述,但是长度不确定。不过好在有空行标记边界,这样就可以和实际内容区分开。

依然用 curl 测试。

Terminal window
$ curl https://plantree.me -v
> GET / HTTP/1.1
> Host: plantree.me
> User-Agent: curl/8.8.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Age: 7971
< Cache-Control: public,max-age=0,must-revalidate
< Cache-Status: "Netlify Edge"; hit
< Content-Length: 23593
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 22 Aug 2024 08:49:35 GMT
< Server: Netlify
<
<!DOCTYPE html><html lang="zh-CN" class="scroll-pt-24"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src https://*; child-src 'none'; script-src-elem https://cdn.skypack.dev https://www.googletagmanager.com https://pagead2.googlesyndication...

2.3 安全性

基于 HTTP,有个超文本传输安全协议(HyperText Transfer Protocol Secure, HTTPS)。名字看着挺厉害,其实就是 HTTP over TLS,本质还是 HTTP,只不过传输层用的是 TLS,一种加密通信层。

简单来说,就是协议内容还是 HTTP,但是加解密借助 TLS。

主要目的,是提供服务器的身份认证(避免访问到冒牌网站),数据交换的隐私与完整性(只有通信双方知道通信内容,第三方不可见)。

3. HTTP 启示

大家平时接触到的形形色色的产品,网站也好,APP 也罢,背后庞大的数据交互,都由 HTTP 承载。

可见,这是一个相当通用,且相当健壮的协议。自从 20 世纪 90 年代被发明以来,不断更新,历久弥新,很了不起。

当然,核心的设计理念,没有发生太大变化。

我大致总结出三点:简单,可扩展,无状态。

HTTP 协议只有两种类型,请求和响应。内容也是结构化的,但不像 JSON 那样冗长,十分精简,一行一行排列。且都是明文,不仅对于机器可读,对开发者也很友好,容易定位错误。

HTTP 内容虽然有结构,但是结构内容可以不断追加。比如,增加新的请求方法,增加 header 字段等,兼容性也容易得到保障。

无状态,我认为是 HTTP 设计中最精妙的部分。HTTP 认为每一次请求都是独立的,没有上下文,没有状态需要维护。就像计算机领域中的纯函数,干净,纯粹,没有副作用。没有需要维护的状态,犯错的机会就少了。

4. 总结

HTTP 协议很简单,相关的 RFC 文件也不大。

不过要设计出这种简单的协议,并不是一件容易的事。

或者换句话说,简单只是表象。简单的背后,有着极为复杂的一面,对事物的深刻洞察,对问题的系统思考,对各种权衡的折衷。

可见,简单,有时候也不简单。

(完)

参考

  1. HTTP 权威指南 (豆瓣)🔗
  2. Cloudflare Radar🔗
在 GitHub 上编辑本页面

最后更新于: 2024-11-20T09:44:17+08:00