这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 HTTP 是现代应用最常用的应用层协议。理解 HTTP 不只是会发 GET 和 POST,还要理解方法语义、状态码、头部、缓存、幂等、认证、跨域、压缩和消息边界。这些语义直接影响接口正确性、重试安全和 CDN 效果。
14.1 HTTP 请求与响应
请求:
POST /api/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 45
Authorization: Bearer <token>
{"userId":10001,"skuId":20001,"quantity":1}
响应:
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 58
Location: /api/orders/100000001
{"orderId":100000001,"status":"CREATED"}
HTTP/1.1 明文文本协议,但 HTTP/2 和 HTTP/3 使用二进制分帧,语义仍保持请求响应模型。
14.2 方法语义
| 方法 | 语义 | 幂等 | 安全 |
|---|---|---|---|
| GET | 读取资源 | 是 | 是 |
| HEAD | 读取元数据 | 是 | 是 |
| OPTIONS | 查询能力 | 是 | 是 |
| POST | 创建或执行动作 | 否 | 否 |
| PUT | 替换资源 | 是 | 否 |
| PATCH | 部分更新 | 不保证 | 否 |
| DELETE | 删除资源 | 是 | 否 |
“安全”表示不改变服务端资源状态,“幂等”表示同一请求执行多次结果一致。
POST 不幂等的典型例子:
POST /orders 第一次创建订单 1001
POST /orders 重试后创建订单 1002
要安全重试 POST,需要业务幂等键:
Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
14.3 状态码
| 类别 | 含义 | 常见状态码 |
|---|---|---|
| 1xx | 中间状态 | 101 Switching Protocols |
| 2xx | 成功 | 200、201、204、206 |
| 3xx | 重定向和缓存 | 301、302、304、307、308 |
| 4xx | 客户端错误 | 400、401、403、404、409、429 |
| 5xx | 服务端错误 | 500、502、503、504 |
易混状态码:
401 Unauthorized:未认证;403 Forbidden:已认证但无权限;409 Conflict:资源状态冲突;429 Too Many Requests:限流;502 Bad Gateway:网关收到无效响应;503 Service Unavailable:服务暂不可用;504 Gateway Timeout:网关等待上游超时。
14.4 常用头部
| Header | 作用 |
|---|---|
| Host | 请求目标主机 |
| Content-Type | 请求体类型 |
| Content-Length | 请求体长度 |
| Transfer-Encoding | 传输编码 |
| Accept | 客户端可接受类型 |
| Cache-Control | 缓存策略 |
| ETag / If-None-Match | 协商缓存 |
| Last-Modified / If-Modified-Since | 时间协商 |
| Cookie / Set-Cookie | 会话 |
| Authorization | 认证凭据 |
| Origin / Referer | 来源 |
| X-Forwarded-For | 代理链路客户端地址 |
| X-Forwarded-Proto | 原始协议 |
| Retry-After | 重试建议 |
代理传递客户端信息时,应确保入口可信并覆盖外部传入的转发头。
14.5 缓存语义
强缓存:
Cache-Control: public, max-age=3600
协商缓存:
ETag: "v1"
If-None-Match: "v1"
命中协商缓存返回:
HTTP/1.1 304 Not Modified
常见指令:
| 指令 | 含义 |
|---|---|
| public | 允许共享缓存 |
| private | 只允许浏览器等私有缓存 |
| no-cache | 可缓存,但使用前需验证 |
| no-store | 不保存响应 |
| max-age | 最大缓存时间 |
| s-maxage | 共享缓存时间 |
| must-revalidate | 过期后必须验证 |
静态资源适合内容哈希加长缓存;动态接口需谨慎,避免用户数据被共享缓存。
14.6 连接与长连接
HTTP/1.1 默认长连接:
Connection: keep-alive
请求分界:
- Content-Length;
- Transfer-Encoding: chunked;
- HTTP/2 帧;
- WebSocket 升级后自定义协议。
短连接的问题:
- 每次请求增加 TCP 握手;
- HTTPS 增加 TLS 握手;
- TIME_WAIT 增多;
- 高延迟链路首包变慢。
14.7 Cookie、CORS 与 SameSite
Cookie 响应:
Set-Cookie: sid=abc; Path=/; HttpOnly; Secure; SameSite=Lax
属性:
| 属性 | 作用 |
|---|---|
| HttpOnly | 禁止 JS 读取 |
| Secure | 仅 HTTPS 发送 |
| SameSite | 跨站发送限制 |
| Domain / Path | 作用范围 |
| Max-Age / Expires | 过期时间 |
CORS 简单示例:
Origin: https://www.example.com
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Credentials: true
跨域是浏览器安全策略,服务端 curl 不受同源策略限制。带凭据时不能使用 * 作为允许来源。
14.8 压缩与范围请求
压缩:
Accept-Encoding: gzip, br
Content-Encoding: gzip
范围请求:
Range: bytes=1000-1999
响应:
HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-1999/10000
适用:
- 大文件下载;
- 断点续传;
- 视频拖动;
- CDN 分片。
注意:动态压缩会消耗 CPU;加密内容无法在代理层基于明文优化;小响应压缩可能得不偿失。
14.9 HTTP 客户端实践
curl -v https://www.example.com
curl -o /dev/null -s -w \
'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' \
https://www.example.com
客户端必须设置:
- 连接超时;
- 读取总超时;
- 最大响应体;
- 重试策略;
- 幂等约束;
- 连接池上限;
- 空闲连接回收;
- 熔断和限流。
常见错误:
- 不设超时;
- 对 POST 无条件重试;
- 连接池无限增长;
- 忽略 429 和 Retry-After;
- 把 5xx 全部当可重试;
- 不关闭响应体。
本章小结
HTTP 语义由方法、状态码、头部和消息体组成。GET/PUT/DELETE 具有明确幂等语义,POST 需要业务幂等键才能安全重试。Cache-Control、ETag 和 304 决定缓存效率,Cookie、SameSite 和 CORS 影响浏览器安全,压缩与范围请求影响传输效率。生产客户端必须治理超时、重试、连接池和响应体释放。
思考题
- 幂等和安全方法分别表示什么?
- 301、302、307、308 的关键差异是什么?
- no-cache 和 no-store 有什么区别?
- 为什么带凭据的 CORS 不能返回
*? - 为一个订单接口设计状态码、幂等键和重试策略。