Skip to content

HTTP 语义、缓存与版本演进 ​

内容摘要:超文本传输协议(Hypertext Transfer Protocol,HTTP)是一组无状态的应用层请求/响应语义。GET、POST、状态码、字段和缓存语义由 RFC 9110/9111 定义;HTTP/1.1、HTTP/2、HTTP/3 只是不同的线上表达和传输映射。本章讲清方法安全性与幂等性、消息 framing、缓存新鲜度与条件请求、内容协商、Cookie/CORS、代理头,以及三个版本的持久连接、多路复用、流控和队头阻塞差异。

难度:高级 | 前置知识:13 TCP 连接、14 TCP 性能、15 DNS | 所属层次:应用层

一、HTTP 语义与版本编码 ​

HTTP 定义“客户端希望对资源做什么”以及“服务端结果是什么”,而不是规定后端如何实现。

同一个语义请求:

text
GET https://www.example.com/manual HTTP semantics

在 HTTP/1.1 中表示为文本 request-line 和 Host;在 HTTP/2/3 中表示为 :method、:scheme、:authority、:path 伪头及 HEADERS/DATA 帧。应用看到的资源、方法与状态码不因版本而改变。

无状态不等于服务没有状态 ​

“HTTP 无状态”表示每个请求的协议语义可以独立解释,不要求服务端由 HTTP 协议自动记住前一次请求。应用仍可通过:

  • Cookie + 服务端 Session。
  • Bearer Token/JWT。
  • URL/请求体中的业务标识。
  • TLS 客户端证书或其他认证上下文。

维持用户状态。状态安全边界由应用设计,不是 HTTP 自动保证。

二、URL、Origin 与请求目标 ​

URL 示例:

text
https://www.example.com:443/docs/network?q=http#cache
部分值是否发送给服务器
schemehttps决定安全连接与默认端口
hostwww.example.com用于 DNS、SNI、证书和 HTTP authority
port443建连目标;默认值可省略
path/docs/network是
queryq=http是;可能进入日志/Referer,勿放秘密
fragmentcache通常只在客户端处理,不随 HTTP 请求发送

Web 同源(origin)由:

text
scheme + host + port

组成。路径不同仍可同源;http 与 https、不同端口或不同主机均为不同源。

三、HTTP/1.1 消息与 framing ​

RFC 9112 定义 HTTP/1.1 线格式:

text
HTTP-message = start-line CRLF
               *(field-line CRLF)
               CRLF
               [message-body]

请求:

http
GET /note HTTP/1.1
Host: www.example.com
Accept: text/html
Connection: close

响应:

http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 11
Connection: close

hello-http

1、本机真实原始响应 ​

本机 Python 3.9.6 在 127.0.0.1 启动一次性 HTTP/1.1 服务,socket 发送上述请求,真实输出:

text
HTTP/1.1 200 OK
Server: BaseHTTP/0.6 Python/3.9.6
Date: Mon, 07 Sep 2026 11:37:24 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 11
Connection: close

hello-http

日期和临时端口随运行变化;这只验证 framing,不代表 Python 内置 server 适合生产。

2、消息体长度 ​

HTTP/1.1 必须无歧义地确定消息边界,常见方式:

  • Content-Length: N:接收恰好 N 字节。
  • Transfer-Encoding: chunked:每块带十六进制长度,以 0 长块结束。
  • 特定状态/方法无 body,如 HEAD 响应、1xx、204、304。
  • 响应通过连接关闭定界,降低连接复用能力。

如果前端代理与后端对 Content-Length、Transfer-Encoding 或非法空白的解析不一致,可能产生 HTTP Request Smuggling(请求走私)。正确做法是严格按 RFC 9112 解析、拒绝歧义消息,并统一代理链实现。

四、方法:安全性、幂等性与可缓存性 ​

方法典型语义SafeIdempotent通常是否带请求内容
GET获取资源表示是是不应依赖请求内容语义
HEAD仅获取与 GET 类似的响应字段是是通常否
POST让资源按自身语义处理内容否否是
PUT用给定表示创建/替换目标资源状态否是是
DELETE删除目标资源关联否是可有但互操作性谨慎
OPTIONS查询通信选项是是可选
CONNECT建立隧道否否按扩展语义
TRACE环回诊断是是否;生产常禁用

Safe 表示客户端不请求改变服务器状态,不代表服务器绝不记录日志或计费。Idempotent 表示同一意图重复执行的预期效果与执行一次相同,不代表响应字节或状态码相同。

重试规则:

  • GET/HEAD/PUT/DELETE 在协议语义上幂等,但仍需考虑认证、时限和业务实现是否违规。
  • POST 默认不可安全自动重试;支付/创建类接口应设计 Idempotency-Key、唯一业务键或事务去重。
  • 客户端不能仅凭“没有收到响应”判断服务端没有执行(12)。

五、状态码 ​

类别含义常见状态注意
1xx临时信息100、103后续仍有最终响应
2xx请求成功处理200、201、202、204、206202 只表示已接受,不代表任务完成
3xx重定向/缓存验证301、302、303、304、307、308307/308 保留方法;304 不是普通重定向
4xx客户端请求问题400、401、403、404、409、412、429401 实际表示需认证,403 表示拒绝
5xx服务端/网关失败500、502、503、504502 与 504 是不同的上游失败阶段

常见网关错误边界 ​

  • 502 Bad Gateway:代理从上游收到无效响应或连接被重置等。
  • 503 Service Unavailable:服务当前不可用/过载,可配 Retry-After。
  • 504 Gateway Timeout:网关等待上游响应超时。

状态码只能说明生成该响应的 HTTP 节点如何分类问题。定位时还需代理/LB/应用日志和各阶段时延。

六、字段、内容与内容协商 ​

1、常见字段 ​

字段方向用途风险/误区
Host / :authority请求目标 authority/虚拟主机Host 注入、错误信任代理值
Content-Type双向内容媒体类型与实际内容不符导致嗅探风险
Content-Length双向内容长度与 TE 冲突可能请求走私
Accept请求可接受媒体类型无匹配可返回 406
Accept-Encoding请求gzip/br 等内容编码压缩侧信道与 CPU 开销
Authorization请求凭证绝不能记录或转发到错误上游
Location响应重定向/新资源位置开放重定向
Retry-After响应建议重试时间客户端仍需重试预算和抖动
Vary响应扩充缓存键Vary: * 不可复用;过多维度降低命中率

2、内容协商 ​

客户端可发送:

http
Accept: application/json, text/html;q=0.8
Accept-Encoding: br, gzip
Accept-Language: zh-CN, en;q=0.7

服务端选择表示并用 Content-Type、Content-Encoding、Content-Language 描述。若响应会随请求字段变化,共享缓存需要正确的 Vary,否则可能把一种语言或压缩格式错误返回给其他客户端。

七、HTTP 缓存 ​

缓存的目标是复用先前响应,降低时延和带宽。需要区分:

  • Private cache:单用户浏览器/客户端缓存。
  • Shared cache:CDN、反向代理或组织代理,供多个用户复用。
  • Freshness:缓存响应是否足够新,可否不联系 origin 直接使用。
  • Validation:过期后携带 validator 询问 origin 是否仍有效。

1、Cache-Control 易混指令 ​

指令含义
max-age=60响应在 60 秒内可视为新鲜
s-maxage=300共享缓存优先使用 300 秒
private可存于私有缓存,不得存于共享缓存
public显式允许共享缓存按规则存储
no-cache可存储,但复用前必须验证
no-store缓存不得存储该响应
must-revalidate过期后必须成功验证才可复用,除非其他规范明确允许

no-cache 不等于“不缓存”。敏感响应通常需要同时评估 no-store、private、认证语义以及应用/浏览器历史记录;单一字段不是所有泄露面的万能开关。

2、ETag 与条件请求 ​

  • If-None-Match/ETag 通常优先于日期 validator。
  • 强 ETag 用于字节级一致性语义;弱 ETag W/"..." 表示语义等价但可能非字节相同。
  • Last-Modified + If-Modified-Since 精度和时钟语义更弱。
  • 304 不携带新的完整表示内容,客户端复用缓存 body。

3、本机缓存实验 ​

本机 Python HTTP server 首次返回 ETag,第二次携带 If-None-Match:

text
first: 200 etag="kb-v1" cache=max-age=60 body=knowledge-v1
revalidate: 304 etag="kb-v1" body-bytes=0

这验证条件请求协议,不代表浏览器/CDN 必然采用相同缓存策略。

八、HTTP/1.0、1.1、2 与 3 ​

维度HTTP/1.0HTTP/1.1HTTP/2HTTP/3
主要规范RFC 1945RFC 9112RFC 9113RFC 9114
传输TCPTCPTCP,通常 TLSQUIC/UDP,内建 TLS 1.3
线格式文本文本二进制 frameQUIC stream 上二进制 frame
持久连接非默认默认单连接长期复用单 QUIC 连接长期复用
并发多连接多连接/管线化多 stream 复用多 QUIC stream 复用
头压缩无无HPACKQPACK
应用层 HOL单连接/管线化明显管线化明显stream 间减少stream 间减少
传输层 HOLTCPTCP一个 TCP 丢包可阻塞所有 stream丢包通常只阻塞相关 QUIC stream
连接迁移无无无QUIC Connection ID 支持

1、HTTP/1.1 ​

  • 默认持久连接,减少 TCP/TLS 握手。
  • Pipelining 可连续发送请求,但响应必须按请求顺序,应用层队头阻塞严重,部署有限。
  • 浏览器常开多条 TCP 连接获得并发,增加拥塞状态与资源占用。

2、HTTP/2 ​

  • 帧交错传输,stream 逻辑独立。
  • 连接级和 stream 级流量控制。
  • HPACK 压缩重复字段。
  • TCP 只看到一个有序字节流,任意 TCP 段丢失可让所有 stream 等待。
  • RFC 9113 已弃用 RFC 7540 的原始优先级信令;新部署需核对实际客户端/服务端策略。

3、HTTP/3 ​

  • HTTP 语义映射到 QUIC stream。
  • QUIC 在 UDP 上实现可靠传输、拥塞控制、TLS 1.3 和连接迁移。
  • 单个 stream 丢包通常不阻塞其他 stream 的有序交付。
  • 使用 QPACK,避免直接复制依赖全局有序交付的 HPACK。
  • UDP 被阻断时,客户端应回退 TCP 版本;“支持 HTTP/3”不代表每次请求都实际用了 HTTP/3。

九、版本发现与协商 ​

  • HTTPS 上 HTTP/2 使用 TLS ALPN 标识 h2。
  • h2c cleartext upgrade 在 RFC 9113 中已弃用;受控内部 prior knowledge 仍是另一种机制。
  • HTTP/3 可通过 Alt-Svc: h3=":443"、HTTPS DNS RR 或客户端已知信息发现。
  • ALPN 是双方能力交集,不是客户端单方面强制。

本机 curl 8.7.1(nghttp2 1.68.1)实测:

text
默认:https://example.com/ → http_version=2 code=200
强制 --http1.1           → http_version=1.1 code=200
TLS ALPN                 → h2

本机 curl 未显示 HTTP/3 feature,故未执行 HTTP/3 实测,也未伪造对比输出。

十、Cookie、Session、同源与 CORS ​

1、Cookie 与 Session ​

服务端:

http
Set-Cookie: session_id=opaque-value; Secure; HttpOnly; SameSite=Lax; Path=/

客户端后续自动携带:

http
Cookie: session_id=opaque-value

安全属性:

  • Secure:仅通过安全传输发送。
  • HttpOnly:脚本不能直接读取,降低部分 XSS 窃取风险。
  • SameSite:限制跨站场景自动携带,降低 CSRF 风险。
  • Domain/Path:定义发送范围,不是强认证或文件系统权限。
  • Session ID 应高熵、可撤销、轮换,服务端不得把敏感状态直接信任为未签名 Cookie。

2、同源策略与 CORS ​

同源策略(Same-Origin Policy,SOP)是浏览器安全模型;跨域资源共享(Cross-Origin Resource Sharing,CORS)是服务端用响应字段授权浏览器脚本读取跨源响应。

关键边界:

  • CORS 不是防火墙,也不阻止非浏览器客户端发送请求。
  • 简单请求可能不预检;浏览器仍根据响应字段决定脚本能否读取。
  • 携带凭证时不能使用任意 Access-Control-Allow-Origin: *。
  • Origin 校验必须精确匹配允许列表,不能用脆弱后缀/子串判断。

十一、代理与转发字段 ​

每个中间节点同时扮演下游 server 和上游 client。常见字段:

  • 标准 Forwarded: for=192.0.2.10;proto=https;host=www.example.com
  • 事实标准 X-Forwarded-For、X-Forwarded-Proto、X-Forwarded-Host
  • 分布式追踪 traceparent

信任规则:

  1. 边界代理删除客户端伪造的受信转发字段,再写入自己的值。
  2. 应用只信任明确代理网段/身份写入的 hop。
  3. 限制链长度与字段大小,日志脱敏。
  4. Host/authority、scheme 参与重定向、Cookie 和链接生成时必须校验,防 Host Header Poisoning。

十二、从 URL 到响应的完整链路与时延 ​

curl 常用拆分:

bash
curl -sS -o /dev/null \
  -w 'dns=%{time_namelookup}s tcp=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s http=%{http_version}\n' \
  https://example.com/

本机单次真实观测:

text
dns=0.003894s
tcp=0.109261s
tls=0.222404s
ttfb=0.352832s
http_version=2

阶段增量应计算:

text
TCP 增量 ≈ time_connect - time_namelookup
TLS 增量 ≈ time_appconnect - time_connect
服务等待/请求发送增量 ≈ time_starttransfer - time_appconnect

这些字段是从请求起点累计时间,不应直接把 time_appconnect 全部叫“TLS 耗时”。单次样本也不能代表分布,生产需看 p50/p95/p99 与分地域基线。

十三、HTTP 版本对比实验 ​

bash
curl --http1.1 -sS -o /dev/null \
  -w 'version=%{http_version} total=%{time_total}s\n' https://example.com/
curl --http2 -sS -o /dev/null \
  -w 'version=%{http_version} total=%{time_total}s\n' https://example.com/

本机真实输出:

text
HTTP/2:version=2,code=200
HTTP/1.1:version=1.1,code=200,单次 total=0.313980s

这不是性能基准:两个请求缓存、连接、网络时刻不同,且每个版本只请求一个小对象。公平比较应:

  • 同一地理位置、同一服务器内容和并发模型。
  • 重复采样,区分冷连接/热连接。
  • 记录 DNS/TCP/TLS/TTFB/下载、RTT、丢包和对象数。
  • 用浏览器 waterfall 或 nghttp/支持 HTTP/3 的 curl 观察 stream。

抓包过滤:

text
http
http2
quic
tls.handshake.extensions_alpn_str

HTTPS 下 HTTP/2 内容被 TLS 加密;需受控环境配会话密钥日志才能解密,禁止采集真实用户敏感流量。

十四、安全风险 ​

风险根因防护
请求走私代理链 framing 解析不一致严格 RFC 9112、拒绝 CL/TE 歧义、统一代理
Response Splitting未过滤 CR/LF 写入响应字段结构化 API、禁止原始换行
Host Header Poisoning信任未验证 Host/转发头authority allowlist、可信代理边界
敏感头泄露Authorization/Cookie 被日志或跨域转发日志脱敏、重定向策略、最小转发
缓存投毒/越权cache key 缺少 Host/Vary/认证维度明确缓存键、private/no-store、测试多租户
压缩侧信道秘密与攻击者输入共同压缩隔离秘密、禁用敏感场景压缩、随机化
HTTP/2/3 资源耗尽大量 stream、字段或 resetstream/字段/连接限额、补丁与速率限制

HTTPS 只保护传输机密性、完整性和身份验证边界,不会自动防止 XSS、SQL 注入、SSRF、越权、恶意服务器或敏感日志(17)。

十五、排障清单 ​

  1. 记录 URL、method、HTTP 版本、代理链和复现时刻。
  2. 拆分 DNS、TCP、TLS、TTFB 与下载时间。
  3. 明确状态码由 CDN、LB、网关还是 origin 生成。
  4. 查看 Via、Age、缓存状态字段、trace ID,但注意其可信边界。
  5. 缓存问题同时检查 cache key、Vary、freshness、validator 和 purge。
  6. HTTP/2 问题检查 stream error、GOAWAY、flow-control window 与 TCP 重传。
  7. HTTP/3 问题检查 UDP 可达、QUIC/TLS、Alt-Svc 和 TCP 回退。
  8. 重试前确认方法幂等、预算、退避和服务端是否已经执行。

十六、版本与实现差异 ​

  • 当前 HTTP 核心规范是 RFC 9110/9111;HTTP/1.1/2/3 分别是 RFC 9112/9113/9114。
  • 浏览器连接池、跨 origin coalescing、优先级、HTTP/3 race/fallback 与缓存分区策略随版本变化。
  • CDN 私有缓存字段如 CF-Cache-Status、X-Cache 不是统一标准。
  • Server Push 在标准中存在,但浏览器/服务部署支持已显著收缩;使用前查目标版本。
  • curl 构建功能取决于 TLS/HTTP 库;curl -V 是实验前置证据。

十七、关联章节 ​

检索关键词 ​

HTTP 语义 RFC 9110 HTTP/1.1 报文 framing Content-Length chunked HTTP 方法 safe idempotent HTTP 状态码 502 503 504 Content-Type Content-Encoding Vary HTTP 缓存 max-age no-cache no-store ETag If-None-Match 304 HTTP/2 frame stream HPACK 多路复用 HTTP/2 TCP 队头阻塞 HTTP/3 QUIC QPACK ALPN h2 h3 Cookie Secure HttpOnly SameSite 同源策略 CORS Forwarded X-Forwarded-For HTTP 请求走私

权威来源 ​

HTTP 语义、缓存和各版本传输映射已于 2026-09-07 对照 RFC 9110–9114 核验。HTTP/1.1 原始消息、ETag/304、本机 HTTP/1.1 与 HTTP/2 协商已真实执行;本机 curl 不支持 HTTP/3,因此 HTTP/3 抓包与日志对比明确标记为未执行。

ICP 备案号待补充 · Gitee 主页