HTTP
基于 TCP 协议,是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。
[!info] related notes
HTTP
HTTP(Hypertext Transfer Protocol,超文本传输协议):基于 TCP 协议,是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
HTTP 协议如果不按 1.1、2、3 分开看,可以把它理解成一套“统一接口”:
URI 说明你在和哪个资源打交道,方法说明你想做什么,头字段说明条件与上下文,内容承载输入或输出,状态码说明结果。
RFC 9110 把 HTTP 定义成一族无状态、应用层、请求/响应协议;而 HTTP/1.1、HTTP/2、HTTP/3 主要是在规定这套共同语义如何在线上传输。
1. HTTP 最核心的抽象:资源和表示
HTTP 处理的核心对象不是“文件”,而是资源(resource)。规范明确说,请求的目标叫 resource,HTTP 并不限制资源到底是什么;它只定义了一套与资源交互的接口。资源通常用 URI 标识。更关键的是,HTTP 有意把资源标识和请求语义分开:URI 负责“指向谁”,方法和少量请求头负责“要干什么”。所以,一个 URI 不是天然等于“读文件”或“删记录”,真正的操作语义在方法上。
而客户端真正收发的,往往不是资源本体,而是它的表示(representation)。RFC 9110 把表示定义成“反映资源过去、当前或期望状态的信息”,它由表示元数据和表示数据流组成。于是,从 HTTP 的视角看,HTML、JSON、图片、视频、PDF,本质上都只是不同的表示格式。(IETF Datatracker)
http 和 https 只是两种相关 URI 方案。http URI 对应普通 HTTP 访问;https URI 则要求通过 TLS 保护的 HTTP 通信访问,并且这里的“安全”明确包括服务器被认证为目标 origin 的代表。换句话说,HTTPS 不是另一套语义,而是带传输层安全保护的 HTTP。(IETF Datatracker)
2. HTTP 消息到底在表达什么
从抽象上看,一条 HTTP 消息可以拆成四块:控制数据、头字段、内容、可选的 trailer。规范要求先发控制数据,再发 header section;如果有内容,内容跟在后面;某些版本/分帧机制还允许在最后附带 trailer。头字段可以修改或扩展消息语义、描述发送方、定义内容或提供额外上下文。
另一个很重要但常被忽略的点是:内容的含义不是固定的,而是由方法和响应状态共同决定。 RFC 9110 明说,请求里的 content 含义由方法定义;响应里的 content 含义由请求方法、响应状态码以及相关响应头共同决定。比如,同样是 200 OK,对 GET 来说通常是在返回目标资源的当前表示;对 POST 来说,返回的可能是处理结果,也可能是处理后的新状态。
比如下面这段报文:
GET /users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "u42-v7"
Cache-Control: max-age=60
{"id":42,"name":"Alice"}
这里 /users/42 指向目标资源,GET 表示想取它的当前表示,Accept 表示客户端偏好 JSON,Content-Type 说明响应表示的媒体类型,ETag 是这个表示的校验标识,Cache-Control 告诉缓存如何复用它。也就是说,HTTP 报文不是“只装数据”,而是在同时表达资源、意图、表示格式、缓存规则和结果状态。(IETF Datatracker)
3. 方法(Method)才是 HTTP 语义的核心
HTTP 方法不是“接口名”,而是协议层的标准动作。RFC 9110 规定,通用服务器必须支持 GET 和 HEAD;其他方法是否支持由资源自己决定。若服务器根本不认识某个方法,通常应回 501 Not Implemented;若认识但不允许用于目标资源,通常应回 405 Method Not Allowed。(IETF Datatracker)
方法还有两个非常重要的性质:safe 和 idempotent。safe 表示其定义语义本质上是只读的,客户端不应期待对服务器状态产生变化;idempotent 表示重复发送多个相同请求,其“预期效果”与发一次相同。规范给出的结论是:safe 方法是幂等的,而 PUT、DELETE 也属于幂等方法。幂等的重要意义在于:如果通信中断,客户端更容易安全重试。(IETF Datatracker)
几个最常见的方法,真正的协议语义是这样的:GET 请求目标资源的当前已选表示;HEAD 和 GET 基本一样,但服务器不能在响应里发送内容,通常用于只看元数据;POST 是让目标资源按它自己的语义处理请求中附带的表示;PUT 则是用请求里的表示去创建或替换目标资源的状态;DELETE 请求的是移除“目标资源与当前功能之间的关联”。这也是为什么 POST 和 PUT 不能简单粗暴地理解成“都是上传”。(IETF Datatracker)
这里最容易混淆的是 POST 和 PUT。规范直接强调,它们的根本区别在于:POST 中附带的表示,是交给目标资源“按其自有语义处理”的输入;而 PUT 中附带的表示,则是在定义“目标资源要被替换成什么状态”。所以,如果服务器是替你选 URI,再创建资源,通常更像 POST;如果客户端已经知道确切目标 URI,并要把它改成某个状态,更像 PUT。(IETF Datatracker)
还有一个工程上很实用的细节:规范指出,GET/HEAD 请求里的内容并没有通用定义的语义,某些实现甚至会因为安全风险而拒绝它们。所以“GET 带 body”不是完全非法,但绝不是一个应该默认依赖的通用能力。(IETF Datatracker)
4. 状态码不是“错误码”,而是结果语义
HTTP 状态码按类别工作。1xx 是临时信息响应,表示连接状态或请求进度,且它本身不带内容;2xx 表示请求被成功接收、理解并接受;3xx 表示客户端还需要采取进一步动作,通常是重定向;4xx 表示客户端看起来出了错;5xx 表示服务器在处理一个表面有效的请求时失败了。(IETF Datatracker)
很多常见状态码的“真实含义”其实很细。200 是成功,但成功后返回什么要看方法;201 是已创建;204 和 304 都没有内容;301/302/307/308 都与重定向有关,但语义不完全一样;401 不是“业务无权限”的泛义错误,而是缺少有效认证凭据时的协议级挑战入口;404 表示服务器没有目标资源的当前表示;500 是服务器意外失败。(IETF Datatracker)
5. 头字段:HTTP 的“控制面”
如果方法和状态码是 HTTP 的骨架,那头字段就是它的控制面。规范说明,header fields 会修改或扩展消息语义、描述内容、说明发送者和上下文。也正因为如此,HTTP 才能在不改核心方法的前提下,发展出缓存控制、条件请求、内容协商、认证、范围请求等大量能力。(IETF Datatracker)
在内容描述上,最重要的两个字段是 Content-Type 和 Content-Encoding。规范把表示数据描述成一个两层模型:先是某种媒体类型的数据,再在其外层套内容编码。也就是说,application/json 和 text/html 解决的是“这是什么格式”,而 gzip 之类解决的是“它有没有再被压缩/编码过”。这也是为什么 Content-Encoding: gzip 不是在和 Content-Type: application/json 竞争,而是在它外面再包一层。(IETF Datatracker)
HTTP 还内建了内容协商。RFC 9110 定义了几种协议层可见的协商模式,其中最常见的是服务端根据客户端偏好做主动协商,比如根据 Accept、Accept-Language、Accept-Encoding 选择最合适的表示。如果一个响应会因为这些请求头而变化,服务器应当用 Vary 告诉缓存:这些字段是缓存键的一部分,后续请求只有在对应字段匹配时才能直接复用缓存。(IETF Datatracker)
6. 缓存和条件请求:HTTP 不是“每次都重新下载”
HTTP 的一个巨大优势,是它把缓存做成了协议的一等公民。RFC 9111 说得很直接:缓存的目标,是通过复用先前响应来显著提升性能。一个缓存条目如果还是 fresh,就可以不去源站验证直接复用;不 fresh 时,往往也不是只能丢弃,而是可以通过验证把它“刷新”。(IETF Datatracker)
为了做到这一点,HTTP 使用了验证器(validator),最常见的是 ETag 和 Last-Modified。规范建议 origin server 为能稳定判断变化的表示发送 ETag,因为它对条件请求和缓存新鲜度评估都很重要。客户端随后可以发 If-None-Match 或 If-Modified-Since 这样的条件请求;如果服务端判断资源没变,对 GET/HEAD 就可以返回 304 Not Modified,省掉重新传输表示内容。(IETF Datatracker)
缓存并不是“同 URI 就直接命中”那么简单。RFC 9111 规定,缓存只有在目标 URI、方法、被 Vary 指定的请求头、以及 no-cache/验证状态等条件都满足时,才能复用一条已存响应。否则就得重新验证或重新获取。换句话说,HTTP 缓存本质上是“带协议语义的缓存”,不是裸 key-value。(IETF Datatracker)
HTTP 还支持范围请求。服务器可以通过 Accept-Ranges: bytes 告诉客户端它支持字节范围请求,客户端之后就可以只取某个区间,而不是整份表示。这也是下载续传、流媒体拖动、局部读取大文件等能力的协议基础。(IETF Datatracker)
7. 中间层:HTTP 为什么适合大规模网络
HTTP 从设计上就支持中间层。规范列出的三种常见 intermediary 是 proxy、gateway、tunnel;此外还有 cache。一次请求/响应完全可能经过多段独立连接,不是永远只有“浏览器直连源站”这一种形态。(IETF Datatracker)
这点非常关键,因为它解释了 HTTP 为什么能长成今天的 Web 基础设施:代理可以做访问控制与转发,网关可以把 HTTP 接到别的后端协议或服务上,隧道可以转成透明字节通道,缓存可以部署在客户端、代理节点、CDN 或企业网络里来减少带宽和延迟。RFC 9110 在缓存一节甚至直接提到代理缓存层级和 CDN 这类架构。(IETF Datatracker)
8. 认证与安全:HTTP 里也有协议级身份机制
HTTP 自己带有认证挑战/应答框架。服务器在需要认证而客户端没带有效凭据时,应返回 401 Unauthorized,并附带 WWW-Authenticate 指出可用认证方案;客户端随后可以通过 Authorization 头带上凭据重新请求。代理认证则对应 407、Proxy-Authenticate 和 Proxy-Authorization。(IETF Datatracker)
安全传输方面,最核心的是 https。规范把它定义为建立在 TLS 保护上的 HTTP 通信,并要求这里的“secured”包括服务器端身份认证。所以,HTTP 的应用语义本身不负责机密性和完整性;这些通常由 HTTPS 所依赖的 TLS,或者在 HTTP/3 场景下由 QUIC 所集成的安全能力来提供。(IETF Datatracker)
9. 版本只是“传法不同”,不是“协议重写”
如果你已经学过 HTTP/1.1 和 HTTP/2,再回看 HTTP 本身,会更容易明白:HTTP 的本体更像“语义层”,版本更像“线缆上的表达层”。 RFC 9110 定义共享语义;RFC 9112 规定 HTTP/1.1 的消息语法、解析和连接管理;RFC 9113 说明 HTTP/2 是这套语义的优化表达,通过头字段压缩和同连接多并发交换降延迟;RFC 9114 则把 HTTP 语义映射到 QUIC 上。(IETF Datatracker)
所以你可以把这几版理解为:
HTTP/1.1 更像文本报文;HTTP/2 更像二进制分帧加多路复用;HTTP/3 则把 HTTP 放到了 QUIC 之上。但无论哪一版,资源、表示、方法、状态码、头字段、缓存、条件请求这些核心语义都没变。(IETF Datatracker)
10. 几个最容易被误解的点
第一,HTTP 不是“传网页的协议”。网页只是某种表示,HTTP 传的是资源的表示,完全可以是 JSON、图片、音频、视频、字节范围、甚至错误说明。(IETF Datatracker)
第二,safe 不等于“绝对没副作用”,idempotent 也不等于“响应完全一样”。safe 说的是客户端请求的语义本质上是只读;服务器仍然可以记录日志等。idempotent 说的是多次相同请求的预期效果相同,响应内容本身未必字节级一样。(IETF Datatracker)
第三,DELETE 不等于“物理删除磁盘里的东西”。规范定义的是移除目标资源和当前功能之间的关联;底层是否销毁数据、归档、回收存储,都取决于资源实现。(IETF Datatracker)
第四,URI 里写了动作,不代表你就能用 GET 去做这个动作。规范明确要求,资源所有者必须保证通过 safe 方法访问时,不会执行不安全行为;像 ?do=delete 这种设计,如果用 GET 真触发删除,会破坏 HTTP 的基本语义。(IETF Datatracker)
一句话收尾:
HTTP 协议本身,真正要学的不是“某个版本的报文格式”,而是这套统一语义:资源、表示、方法、状态码、头字段、缓存、条件请求、中间层和安全。
版本演进是在优化“怎么传”,而 HTTP 本体回答的是“这些交互到底意味着什么”。
面试要点
来自 http-vs-https-interview-question 的面试视角整理。
一句话回答
HTTPS 可以理解成“HTTP + TLS”,在 HTTP 之上增加了加密、身份校验和数据完整性保护。
最核心的区别
- HTTP 明文传输
- HTTPS 会经过 TLS 握手并建立加密通道
- HTTPS 能减少中间人篡改和窃听风险
面试时最常说的 3 个安全点
- 机密性:内容被加密
- 完整性:能发现传输内容是否被篡改
- 身份认证:通过证书验证服务端身份
常见追问
HTTPS 比 HTTP 多了什么过程
主要多了 TLS 握手、证书校验和密钥协商。
HTTPS 一定绝对安全吗
不是。它主要解决传输层安全问题,但 XSS、CSRF、弱密码、业务漏洞仍然可能存在。
最短记忆方式
HTTPS = 在 HTTP 之上加一层 TLS 安全通道。