计算机网络之 HTTP 协议详解
一、HTTP 概述
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网中最基础、最重要的应用层协议之一。它定义了客户端(通常是浏览器)与服务器之间通信的规则和格式,是万维网数据通信的基础。
1.1 HTTP 的发展历程
| 版本 | 年份 | 核心特性 |
|---|---|---|
| HTTP/0.9 | 1991 | 极简协议,只支持 GET 方法,无请求头 |
| HTTP/1.0 | 1996 | 增加请求头、响应头、POST 方法、状态码 |
| HTTP/1.1 | 1997 | 长连接(默认 keep-alive)、管线化、分块传输、Host 头 |
| HTTP/2 | 2015 | 多路复用、头部压缩(HPACK)、服务器推送、二进制帧 |
| HTTP/3 | 2022 | 基于 QUIC 协议(UDP)、0-RTT 建连、解决队头阻塞 |
1.2 HTTP 的特点
- 无状态:服务器不会在两个请求之间保留任何客户端的状态信息。Cookie 和 Session 机制的出现就是为了弥补这一特性。
- 请求-响应模型:客户端发起请求,服务器返回响应,一问一答。
- 基于 TCP/IP:HTTP 位于应用层,底层依赖 TCP 提供可靠传输(HTTP/3 除外,基于 QUIC/UDP)。
- 可扩展:通过自定义头部字段和状态码,HTTP 具有很强的扩展能力。
二、HTTP 报文结构
HTTP 报文分为两类:请求报文 (Request)和响应报文(Response)。
2.1 请求报文结构
POST /api/users HTTP/1.1 ← 请求行(方法 + URI + 版本)
Host: www.example.com ← 请求头
Content-Type: application/json
Content-Length: 36
Authorization: Bearer token_xxx
{"name": "zhangsan", "age": 25} ← 请求体
请求行由三部分组成:
- 请求方法:GET、POST、PUT、DELETE 等
- 请求 URI:资源路径
- HTTP 版本:HTTP/1.0、HTTP/1.1 等
2.2 响应报文结构
HTTP/1.1 200 OK ← 状态行(版本 + 状态码 + 原因短语)
Content-Type: application/json ← 响应头
Content-Length: 42
Cache-Control: max-age=3600
{"id": 1, "name": "zhangsan"} ← 响应体
状态行由三部分组成:
- HTTP 版本
- 状态码:如 200、404、500
- 原因短语:如 OK、Not Found
三、HTTP 请求方法
| 方法 | 作用 | 是否有请求体 | 是否安全 | 是否幂等 |
|---|---|---|---|---|
| GET | 获取资源 | 否 | 是 | 是 |
| POST | 提交数据/创建资源 | 是 | 否 | 否 |
| PUT | 全量替换资源 | 是 | 否 | 是 |
| PATCH | 局部更新资源 | 是 | 否 | 否 |
| DELETE | 删除资源 | 否(一般) | 否 | 是 |
| HEAD | 获取响应头(不返回响应体) | 否 | 是 | 是 |
| OPTIONS | 查询支持的通信选项 | 否 | 是 | 是 |
| TRACE | 回显服务器收到的请求 | 否 | 是 | 是 |
关键概念说明
- 安全:指请求不会改变服务器上的资源状态。GET、HEAD、OPTIONS 是安全的。
- 幂等:指多次执行同一请求,效果与执行一次相同。GET、PUT、DELETE 是幂等的。
RESTful API 中的常见用法
GET /api/users # 获取用户列表
GET /api/users/1 # 获取 ID 为 1 的用户
POST /api/users # 创建新用户
PUT /api/users/1 # 全量更新 ID 为 1 的用户
PATCH /api/users/1 # 局部更新 ID 为 1 的用户
DELETE /api/users/1 # 删除 ID 为 1 的用户
四、HTTP 状态码
状态码分为 5 大类,共几十个具体状态码。日常开发中最常用的不过十几个。
4.1 状态码分类
| 范围 | 含义 | 常见状态码 |
|---|---|---|
| 1xx | 信息性 | 100 Continue |
| 2xx | 成功 | 200 OK、201 Created、204 No Content |
| 3xx | 重定向 | 301、302、304、307、308 |
| 4xx | 客户端错误 | 400、401、403、404、405、429 |
| 5xx | 服务器错误 | 500、502、503、504 |
4.2 常用状态码详解
2xx 成功
| 状态码 | 含义 | 场景 |
|---|---|---|
| 200 OK | 请求成功 | GET/PUT/PATCH 返回数据 |
| 201 Created | 资源创建成功 | POST 创建新资源 |
| 204 No Content | 成功但无返回内容 | DELETE 删除成功 |
3xx 重定向
| 状态码 | 含义 | 场景 |
|---|---|---|
| 301 Moved Permanently | 永久重定向 | 域名迁移、HTTP → HTTPS |
| 302 Found | 临时重定向 | 临时跳转 |
| 304 Not Modified | 未修改,使用缓存 | 协商缓存命中 |
| 307 Temporary Redirect | 临时重定向(保持方法) | POST 重定向时不改为 GET |
4xx 客户端错误
| 状态码 | 含义 | 场景 |
|---|---|---|
| 400 Bad Request | 请求参数错误 | 参数校验失败 |
| 401 Unauthorized | 未认证 | 缺少或无效的 Token |
| 403 Forbidden | 无权限 | 已认证但无权访问该资源 |
| 404 Not Found | 资源不存在 | 接口地址或资源 ID 错误 |
| 405 Method Not Allowed | 方法不允许 | 用 GET 请求只支持 POST 的接口 |
| 429 Too Many Requests | 请求过于频繁 | 触发限流 |
5xx 服务器错误
| 状态码 | 含义 | 场景 |
|---|---|---|
| 500 Internal Server Error | 服务器内部错误 | 未捕获的异常 |
| 502 Bad Gateway | 网关错误 | Nginx 转发到后端服务失败 |
| 503 Service Unavailable | 服务不可用 | 服务器过载或维护中 |
| 504 Gateway Timeout | 网关超时 | 后端服务处理超时 |
五、HTTP 常用头部字段
5.1 通用头部(请求和响应都能用)
| 头部字段 | 作用 | 示例 |
|---|---|---|
Connection |
控制连接是否保持 | keep-alive |
Content-Length |
请求体/响应体的字节长度 | 1024 |
Content-Type |
数据的媒体类型 | application/json |
Transfer-Encoding |
传输编码方式 | chunked |
Cache-Control |
缓存控制策略 | max-age=3600, no-cache |
5.2 请求头部
| 头部字段 | 作用 | 示例 |
|---|---|---|
Host |
目标服务器域名和端口 | www.example.com |
User-Agent |
客户端信息 | Mozilla/5.0 ... |
Accept |
客户端能接受的数据类型 | application/json |
Authorization |
认证凭据 | Bearer xxx_token |
Cookie |
携带 Cookie | session_id=abc123 |
Referer |
请求来源页面 | https://www.google.com |
Origin |
请求来源(跨域用) | https://www.example.com |
If-None-Match |
协商缓存(ETag) | "33a64df5" |
If-Modified-Since |
协商缓存(最后修改时间) | Mon, 01 Jan 2024 00:00:00 GMT |
5.3 响应头部
| 头部字段 | 作用 | 示例 |
|---|---|---|
Set-Cookie |
设置 Cookie | session_id=abc123; HttpOnly |
Location |
重定向目标 URL | https://new.example.com |
ETag |
资源的版本标识 | "33a64df5" |
Last-Modified |
资源最后修改时间 | Mon, 01 Jan 2024 00:00:00 GMT |
Access-Control-Allow-Origin |
CORS 允许的源 | * 或 https://example.com |
X-Request-Id |
请求追踪 ID | a1b2c3d4 |
5.4 Content-Type 常见取值
application/json # JSON 数据
application/x-www-form-urlencoded # 表单数据(默认)
multipart/form-data # 文件上传
text/html # HTML 文档
text/plain # 纯文本
application/xml # XML 数据
application/octet-stream # 二进制流(文件下载)
六、HTTP 缓存机制
缓存是提升性能的重要手段,HTTP 的缓存机制分为强制缓存 和协商缓存。
6.1 强制缓存
强制缓存下,客户端直接使用本地缓存,不向服务器发送请求。通过以下头部控制:
| 头部字段 | 位置 | 作用 |
|---|---|---|
Cache-Control: max-age=3600 |
响应 | 缓存有效期为 3600 秒 |
Cache-Control: no-cache |
响应 | 跳过强制缓存,直接走协商缓存 |
Cache-Control: no-store |
响应 | 不缓存任何内容 |
Expires: Wed, 01 Jan 2025 00:00:00 GMT |
响应 | 缓存过期时间(HTTP/1.0,已不推荐) |
6.2 协商缓存
协商缓存下,客户端会向服务器验证资源是否过期:
方式一:Last-Modified / If-Modified-Since
首次请求:
响应头: Last-Modified: Mon, 01 Jan 2024 00:00:00 GMT
再次请求:
请求头: If-Modified-Since: Mon, 01 Jan 2024 00:00:00 GMT
→ 资源未修改返回 304,资源已修改返回 200 + 新资源
方式二:ETag / If-None-Match
首次请求:
响应头: ETag: "abc123"
再次请求:
请求头: If-None-Match: "abc123"
→ ETag 匹配返回 304,不匹配返回 200 + 新资源
ETag 优先级高于 Last-Modified。
6.3 缓存判断流程
请求发起
│
▼
强制缓存是否过期?
├─ 未过期 → 直接使用缓存(200 from cache)
└─ 已过期
│
▼
发送协商缓存请求
│
▼
资源是否变化?
├─ 未变化 → 返回 304,使用缓存
└─ 已变化 → 返回 200 + 新资源
七、HTTP vs HTTPS
7.1 区别
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 默认端口 | 80 | 443 |
| 安全性 | 明文传输 | 密文传输(TLS/SSL) |
| 证书 | 不需要 | 需要 CA 证书 |
| 性能 | 略快(无加解密开销) | 略慢(TLS 握手开销) |
7.2 HTTPS 的 TLS 握手过程
客户端 服务器
│ │
│──── ClientHello ─────────────>│ ① 客户端发送支持的 TLS 版本、加密套件列表、随机数
│ │
│<─── ServerHello ──────────────│ ② 服务器选择加密套件,发送随机数
│<─── Certificate ─────────────│ ③ 服务器发送数字证书
│<─── ServerHelloDone ─────────│
│ │
│──── ClientKeyExchange ───────>│ ④ 客户端生成预主密钥,用服务器公钥加密后发送
│──── ChangeCipherSpec ────────>│ ⑤ 客户端通知切换为加密通信
│──── Finished ────────────────>│ ⑥ 客户端发送加密的握手完成消息
│ │
│<─── ChangeCipherSpec ─────────│ ⑦ 服务器通知切换为加密通信
│<─── Finished ─────────────────│ ⑧ 服务器发送加密的握手完成消息
│ │
│═══ 加密数据传输 ══════════════│ ⑨ 双方使用对称密钥进行加密通信
关键点:
- 非对称加密用于交换密钥,对称加密用于数据传输(兼顾安全与性能)。
- 通过数字证书确保服务器的身份真实性(防止中间人攻击)。
八、Cookie、Session、Token
8.1 Cookie
服务器设置:
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Strict
客户端存储:
浏览器自动在后续请求中携带 Cookie
常用属性:
| 属性 | 作用 |
|---|---|
HttpOnly |
禁止 JS 访问,防止 XSS 攻击 |
Secure |
仅在 HTTPS 下发送 |
SameSite=Strict/Lax/None |
控制 CSRF 防护级别 |
Domain |
指定 Cookie 生效的域名 |
Path |
指定 Cookie 生效的路径 |
Max-Age |
Cookie 的过期秒数 |
8.2 Session
登录流程:
① 客户端发送用户名和密码
② 服务器验证通过,创建 Session 对象(存储在服务器内存/Redis 中)
③ 服务器返回 Set-Cookie: JSESSIONID=xxx
④ 客户端后续请求自动携带 JSESSIONID
⑤ 服务器根据 JSESSIONID 查找 Session,获取用户信息
8.3 JWT(JSON Web Token)
JWT 结构:
Header.Payload.Signature
示例:
eyJhbGciOiJIUzI1NiJ9. ← Header(算法和类型)
eyJzdWIiOiIxMjM0NTY3ODkwIn0. ← Payload(用户信息)
SflKxwRJSMeKKF2QT4fw ← Signature(签名)
| 对比项 | Cookie + Session | JWT |
|---|---|---|
| 存储位置 | 服务器 | 客户端 |
| 扩展性 | 需要共享 Session(Redis) | 天然支持分布式 |
| 安全性 | 依赖 Cookie 属性 | 注意 XSS 和 Token 泄露 |
| 服务端开销 | 需要存储和查询 | 无状态,无需存储 |
九、HTTP/1.1 的持久连接
HTTP/1.1 默认开启 Connection: keep-alive(持久连接),允许在一个 TCP 连接上发送多个请求。
9.1 管线化(Pipelining)
管线化允许客户端在未收到上一个响应时就发送下一个请求,但存在以下问题:
- 必须按顺序返回响应(队头阻塞)
- 浏览器实际支持不理想
- HTTP/2 用多路复用从根本上解决了这个问题
9.2 队头阻塞问题
在 HTTP/1.1 中,持久连接虽然减少了 TCP 建连开销,但同一连接上的请求必须排队。前面的请求响应慢,后面的请求即使已经到达服务器也只能等待。
十、HTTP/2 核心特性
10.1 二进制帧(Binary Framing)
HTTP/1.1 使用文本格式传输,HTTP/2 将所有传输数据分割为更小的帧(Frame),采用二进制编码,解析更高效。
10.2 多路复用(Multiplexing)
- 在一个 TCP 连接上可以同时发送多个请求和响应
- 通过 Stream ID 区分不同的请求-响应对
- 彻底解决了 HTTP 层的队头阻塞问题
- 但 TCP 层的队头阻塞仍然存在(一个丢包会导致整个连接阻塞)
10.3 头部压缩(HPACK)
HTTP/1.1 中每次请求都会重复发送大量头部(如 User-Agent、Cookie),HTTP/2 使用 HPACK 算法:
- 静态表:预定义了 61 个常见头部
- 动态表:记录之前传输过的自定义头部
- 哈夫曼编码:压缩头部字符串
10.4 服务器推送(Server Push)
服务器可以在客户端请求某个资源时,主动推送相关资源:
客户端请求: index.html
服务器推送: style.css、app.js
实际应用中,浏览器对 Server Push 支持有限,Chrome 已逐步移除该特性。
十一、HTTP/3 核心特性
HTTP/3 基于 QUIC 协议(运行在 UDP 之上),主要改进:
| 特性 | HTTP/2(TCP) | HTTP/3(QUIC/UDP) |
|---|---|---|
| 传输层 | TCP | QUIC(UDP) |
| 建连耗时 | TCP 握手 + TLS 握手 | 合并为一次握手 |
| 0-RTT | 不支持 | 支持(恢复连接时) |
| 队头阻塞 | TCP 层仍有 | 完全解决(流级别的独立传输) |
11.1 0-RTT 连接恢复
QUIC 保存了之前的连接参数(加密密钥等),当客户端再次连接时可以直接发送数据,实现零往返时间的建连。
11.2 解决队头阻塞
TCP 的队头阻塞:一个 TCP 连接上的任意一个数据包丢失,后续所有数据都会被阻塞。
QUIC 的改进:每个 Stream 独立传输,一个 Stream 的丢包不影响其他 Stream 的数据传输。
十二、跨域与 CORS
当浏览器的同源策略(协议 + 域名 + 端口都相同)阻止跨域请求时,需要使用 CORS(Cross-Origin Resource Sharing)机制。
12.1 简单请求
满足以下条件的请求为简单请求,浏览器直接发送:
- 方法为 GET、HEAD、POST
- Content-Type 为
text/plain、multipart/form-data、application/x-www-form-urlencoded - 无自定义头部
12.2 预检请求(Preflight)
不满足简单请求条件时,浏览器会先发送 OPTIONS 请求:
OPTIONS /api/users HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600
12.3 常见 CORS 响应头
| 头部字段 | 作用 |
|---|---|
Access-Control-Allow-Origin |
允许的源(* 表示所有源) |
Access-Control-Allow-Methods |
允许的请求方法 |
Access-Control-Allow-Headers |
允许的请求头 |
Access-Control-Allow-Credentials |
是否允许携带 Cookie |
Access-Control-Max-Age |
预检请求的缓存时间(秒) |
十三、HTTP 中的安全问题
13.1 常见攻击方式
| 攻击类型 | 原理 | 防御方式 |
|---|---|---|
| XSS(跨站脚本) | 注入恶意脚本到页面 | 输出转义、CSP、HttpOnly Cookie |
| CSRF(跨站请求伪造) | 利用已登录的 Cookie 发起伪造请求 | CSRF Token、SameSite Cookie |
| SQL 注入 | 在输入中注入 SQL 语句 | 参数化查询(预编译) |
| 中间人攻击 | 窃听/篡改通信数据 | 使用 HTTPS |
| 点击劫持 | 透明 iframe 覆盖欺骗用户 | X-Frame-Options、CSP |
13.2 安全实践建议
1. 全站使用 HTTPS
2. 设置安全相关的 Cookie 属性:HttpOnly、Secure、SameSite
3. 使用 CSP(Content-Security-Policy)头部防止 XSS
4. 对用户输入进行验证和转义
5. 使用 CSRF Token 防止跨站请求伪造
6. 设置合理的 CORS 策略,避免 Allow-Origin: *
7. 重要的 Cookie 设置 SameSite=Strict
十四、HTTP 性能优化总结
14.1 网络层面
- 使用 HTTPS(HTTP/2、HTTP/3 仅在 HTTPS 上运行)
- 启用 HTTP/2 多路复用
- 合理配置 缓存策略(Cache-Control、ETag)
- 启用 Gzip/Brotli 压缩
14.2 应用层面
- 减少 请求数量(合并资源、雪碧图、代码分割)
- 减小 资源体积(压缩、Tree Shaking、图片优化)
- 使用 CDN 加速静态资源
- 预加载 (preload)和 预获取(prefetch)关键资源
- 合理使用 Service Worker 离线缓存
14.3 DNS 优化
- 使用 DNS 预解析 :
<link rel="dns-prefetch" href="//cdn.example.com"> - 减少 DNS 查询次数(合并域名)
- 使用 HTTPDNS 避免运营商 DNS 劫持
十五、总结
HTTP 协议看似简单,但其背后涉及缓存、安全、性能、版本演进等多个维度的知识。理解 HTTP 协议不仅有助于日常开发调试(排查接口问题、分析网络性能),也是构建高性能、安全可靠的 Web 应用的基础。
核心知识图谱:
HTTP 协议
├── 基础
│ ├── 报文结构(请求行/头部/请求体)
│ ├── 请求方法(GET/POST/PUT/DELETE)
│ └── 状态码(2xx/3xx/4xx/5xx)
├── 进阶
│ ├── 缓存机制(强制缓存 + 协商缓存)
│ ├── HTTPS 与 TLS 握手
│ ├── Cookie / Session / JWT
│ └── CORS 跨域
├── 演进
│ ├── HTTP/1.1(持久连接)
│ ├── HTTP/2(多路复用、头部压缩)
│ └── HTTP/3(QUIC、0-RTT)
└── 安全
├── XSS / CSRF / SQL 注入
└── HTTPS / CSP / SameSite