后端 Web 协议(01):HTTP 协议——方法、状态码、头、缓存、连接复用
更新时间:2026-09-01。本文是
backend/web-protocol/Web 协议第 01 篇,在 Web 协议索引下。HTTP 是 Web 的基础协议,理解方法、状态码、头、缓存控制,才能写出高性能的 HTTP 服务。
本文要回答的问题
- HTTP 请求方法有哪些?GET 和 POST 有什么区别?
- HTTP 状态码分类有哪些?2xx、3xx、4xx、5xx 常见状态码含义?
- 缓存控制头 Cache-Control 有哪些常用选项?
- 持久连接是什么?为什么 keep-alive 提升性能?
一、HTTP 请求方法
| 方法 | 语义 | 是否带 body | 幂等 | 缓存 |
|---|---|---|---|---|
| GET | 获取资源 | 一般不带 | 是 | 可缓存 |
| POST | 创建/提交 | 带 | 否 | 不可缓存(除非加上缓存头) |
| PUT | 替换整个资源 | 带 | 是 | 不可缓存 |
| DELETE | 删除资源 | 可选 | 是 | 不可缓存 |
| HEAD | 获取头 | 不带 | 是 | 用于检查资源存在 |
| OPTIONS | 获取允许的方法 | 不带 | 是 | 用于 CORS 预检 |
| PATCH | 部分更新 | 带 | 否 | 不可缓存 |
GET vs POST 常见误区:
- 误区:GET 在 URL,POST 在 body → 不对,GET 也可以带 body,规范允许(但浏览器不支持)
- 误区:POST 比 GET 安全 → 不对,URL 会被日志记录,body 也会
- 实际区别:GET 语义是读取,POST 语义是创建/提交;GET 可缓存,POST 默认不可缓存
二、HTTP 状态码
1xx 信息
100 Continue—— 继续发送 body(客户端Expect: 100-continue)101 Switching Protocols—— 切换协议(如升级到 WebSocket)
2xx 成功
200 OK—— 成功201 Created—— 创建成功204 No Content—— 成功,但没有内容返回206 Partial Content—— 范围请求成功(断点续传)
3xx 重定向
301 Moved Permanently—— 永久重定向,浏览器缓存302 Found—— 临时重定向,不缓存304 Not Modified—— 资源未修改,客户端从缓存读取307 Temporary Redirect—— 临时重定向,保持方法不变(302 会把 POST 变成 GET)308 Permanent Redirect—— 永久重定向,保持方法不变
4xx 客户端错误
400 Bad Request—— 请求格式错误401 Unauthorized—— 需要认证403 Forbidden—— 禁止访问(认证了也不行)404 Not Found—— 找不到405 Method Not Allowed—— 方法不允许408 Request Timeout—— 请求超时409 Conflict—— 资源冲突413 Payload Too Large—— 请求体太大429 Too Many Requests—— 限流,请求太多
5xx 服务端错误
500 Internal Server Error—— 服务端错误501 Not Implemented—— 不支持该方法502 Bad Gateway—— 网关错误503 Service Unavailable—— 服务不可用(过载、维护)504 Gateway Timeout—— 网关超时
三、常见请求头和响应头
请求头
Host: example.com—— 指定主机名(虚拟主机)Content-Type: application/json—— 请求体类型Content-Length: 1234—— 请求体长度Authorization: Bearer <token>—— 认证令牌Cookie: name=value—— cookieAccept: application/json—— 客户端接受的类型If-Modified-Since: <date>—— 缓存验证If-None-Match: <etag>—— 缓存验证Connection: keep-alive—— 保持连接
响应头
Content-Type: application/json—— 响应体类型Content-Length: 1234—— 响应体长度Cache-Control: max-age=3600—— 缓存控制ETag: "abc123"—— 资源标识,用于缓存验证Set-Cookie: name=value—— 设置 cookieLocation: /new-url—— 重定向目标Connection: keep-alive—— 保持连接
四、HTTP 缓存控制
Cache-Control 选项(响应头)
Cache-Control: public—— 可以被代理缓存Cache-Control: private—— 只能被浏览器缓存,不能被代理缓存Cache-Control: max-age=3600—— 缓存 3600 秒(1 小时)Cache-Control: no-cache—— 每次都要向服务器验证(可以存缓存,但每次验证)Cache-Control: no-store—— 完全不缓存,每次都从头来Cache-Control: must-revalidate—— 缓存过期后必须验证
缓存验证
If-Modified-Since+Last-Modified—— 基于时间验证If-None-Match+ETag—— 基于内容验证(更准确,ETag 是资源指纹)
缓存流程图:
- 第一次请求 → 服务器返回 Cache-Control 和 ETag/Last-Modified → 浏览器缓存
- 第二次请求 → 检查缓存是否过期 → 没过期直接用缓存
- 缓存过期 → 发请求带 If-Modified-Since/If-None-Match → 服务器返回 304(未修改)→ 用缓存,重置过期时间
- 服务器返回 200 → 更新缓存
五、连接复用
HTTP/1.0:默认每个请求建立一个 TCP 连接 → 握手开销大
HTTP/1.1:默认 Connection: keep-alive → 多个请求复用一个 TCP 连接 → 减少握手开销管线化(pipelining): 在同一个连接上连续发多个请求,不用等前一个响应回来 → 但是大多数浏览器默认不开,队头阻塞问题。HTTP/2 用多路复用解决。
六、性能对比
| 版本 | 复用 | 多路复用 | 二进制 | head 压缩 | 服务端推送 |
|---|---|---|---|---|---|
| HTTP/1.0 | 不支持 | - | 文本 | - | - |
| HTTP/1.1 | keep-alive | 不支持(队头阻塞) | 文本 | 不支持 | 不支持 |
| HTTP/2 | 一个连接多路复用 | 支持 | 二进制 | HPACK | 支持 |
| HTTP/3 | UDP QUIC 多路复用 | 支持 | 二进制 | QPACK | 支持 |
七、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| POST 缓存 | POST 默认不缓存,需要缓存要加 Cache-Control | 加 Cache-Control: public, max-age=60 |
| 302 方法改变 | POST 重定向后变成 GET,丢失 body | 用 307/308 保持方法 |
| Cache-Control no-cache vs no-store | 搞混 | no-cache 可以存但要验证,no-store 完全不存 |
| keep-alive 超时 | 连接被服务端关闭,客户端不知道 | 服务端设置合理超时,客户端重试 |
相关与延伸
下一篇:REST API 设计——资源建模、幂等性、错误码、版本管理;HTTP/2 和 HTTP/3,见 HTTP 版本演进。
一句话总结
HTTP 协议:GET 获取资源(幂等可缓存),POST 创建提交(不幂等默认不可缓存);状态码分 1xx(信息)、2xx(成功)、3xx(重定向)、4xx(客户端错误)、5xx(服务端错误);缓存控制用 Cache-Control: max-age,缓存验证用 If-Modified-Since/ETag,304 表示未修改;HTTP/1.1 默认 keep-alive 复用连接减少握手开销,HTTP/2 多路复用解决队头阻塞。