HTTP协议详解
什么是HTTP?
HTTP(HyperText Transfer Protocol,超文本传输协议)是应用层协议,用于在Web浏览器和Web服务器之间传输数据。
HTTP特点
- 无状态:每个请求都是独立的
- 基于TCP:可靠传输
- 明文传输:不安全(HTTPS解决)
- 请求-响应模式:客户端发起请求,服务器响应
HTTP版本
| 版本 | 发布年份 | 特点 |
|---|---|---|
| HTTP/0.9 | 1991 | 只支持GET,无头部 |
| HTTP/1.0 | 1996 | 增加头部、状态码、POST等 |
| HTTP/1.1 | 1997 | 长连接、管道化、缓存 |
| HTTP/2 | 2015 | 二进制协议、多路复用、头部压缩 |
| HTTP/3 | 2022 | 基于QUIC(UDP) |
HTTP请求
请求格式
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: session_id=abc123
[请求体]请求方法
| 方法 | 说明 | 幂等性 | 安全性 |
|---|---|---|---|
| GET | 获取资源 | ✅ | ✅ |
| POST | 提交数据 | ❌ | ❌ |
| PUT | 更新资源 | ✅ | ❌ |
| DELETE | 删除资源 | ✅ | ❌ |
| PATCH | 部分更新 | ❌ | ❌ |
| HEAD | 获取头部 | ✅ | ✅ |
| OPTIONS | 获取支持的方法 | ✅ | ✅ |
| TRACE | 追踪请求 | ✅ | ✅ |
| CONNECT | 建立隧道 | ❌ | ❌ |
幂等性:多次执行结果相同 安全性:不会修改服务器状态
常用请求头
Host: www.example.com # 目标主机
User-Agent: Mozilla/5.0 # 客户端信息
Accept: text/html,application/json # 接受的内容类型
Accept-Language: zh-CN,en # 接受的语言
Accept-Encoding: gzip, deflate, br # 接受的编码
Content-Type: application/json # 请求体类型
Content-Length: 123 # 请求体长度
Authorization: Bearer token # 认证信息
Cookie: session_id=abc123 # Cookie
Referer: https://www.google.com # 来源页面
Connection: keep-alive # 连接方式
Cache-Control: no-cache # 缓存控制HTTP响应
响应格式
HTTP/1.1 200 OK
Date: Mon, 22 Oct 2024 12:00:00 GMT
Server: nginx/1.18.0
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Connection: keep-alive
Set-Cookie: session_id=abc123; HttpOnly
Cache-Control: max-age=3600
<!DOCTYPE html>
<html>
...
</html>状态码
1xx 信息响应
- 100 Continue:继续请求
- 101 Switching Protocols:切换协议(WebSocket)
2xx 成功
- 200 OK:请求成功
- 201 Created:资源已创建
- 202 Accepted:已接受,但未处理完成
- 204 No Content:成功但无内容返回
- 206 Partial Content:部分内容(断点续传)
3xx 重定向
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 304 Not Modified:资源未修改,使用缓存
- 307 Temporary Redirect:临时重定向(不改变请求方法)
- 308 Permanent Redirect:永久重定向(不改变请求方法)
4xx 客户端错误
- 400 Bad Request:请求语法错误
- 401 Unauthorized:未认证
- 403 Forbidden:禁止访问
- 404 Not Found:资源不存在
- 405 Method Not Allowed:方法不允许
- 408 Request Timeout:请求超时
- 413 Payload Too Large:请求体过大
- 429 Too Many Requests:请求过多(限流)
5xx 服务器错误
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误
- 503 Service Unavailable:服务不可用
- 504 Gateway Timeout:网关超时
常用响应头
Content-Type: text/html; charset=UTF-8 # 内容类型
Content-Length: 1234 # 内容长度
Content-Encoding: gzip # 内容编码
Server: nginx/1.18.0 # 服务器信息
Date: Mon, 22 Oct 2024 12:00:00 GMT # 响应时间
Last-Modified: Mon, 22 Oct 2024 10:00:00 GMT # 最后修改时间
ETag: "abc123" # 资源标识
Expires: Mon, 22 Oct 2024 13:00:00 GMT # 过期时间
Cache-Control: max-age=3600 # 缓存控制
Set-Cookie: session_id=abc123 # 设置Cookie
Location: https://www.example.com # 重定向地址
Access-Control-Allow-Origin: * # CORS跨域HTTP缓存
强缓存
不发送请求,直接使用缓存。
# 响应头
Cache-Control: max-age=3600 # 缓存3600秒
Expires: Mon, 22 Oct 2024 13:00:00 GMT # 过期时间Cache-Control指令:
max-age=<seconds>:缓存时间no-cache:需要验证缓存no-store:不缓存public:可被任何缓存private:只能被浏览器缓存must-revalidate:缓存过期必须验证
协商缓存
发送请求,服务器判断是否使用缓存。
Last-Modified / If-Modified-Since
# 第一次请求
响应头:Last-Modified: Mon, 22 Oct 2024 10:00:00 GMT
# 第二次请求
请求头:If-Modified-Since: Mon, 22 Oct 2024 10:00:00 GMT
响应:304 Not Modified(使用缓存)ETag / If-None-Match
# 第一次请求
响应头:ETag: "abc123"
# 第二次请求
请求头:If-None-Match: "abc123"
响应:304 Not Modified(使用缓存)缓存策略
用户操作 | 强缓存 | 协商缓存
----------------|--------|----------
地址栏回车 | ✅ | ✅
F5刷新 | ❌ | ✅
Ctrl+F5强制刷新 | ❌ | ❌Cookie
Cookie格式
Set-Cookie: session_id=abc123; Domain=.example.com; Path=/; Max-Age=3600; Secure; HttpOnly; SameSite=Strict属性:
- Domain:Cookie的域名
- Path:Cookie的路径
- Max-Age:有效期(秒)
- Expires:过期时间
- Secure:只在HTTPS传输
- HttpOnly:禁止JavaScript访问
- SameSite:跨站请求控制
Strict:完全禁止跨站发送Lax:部分允许(GET请求)None:允许跨站发送(需Secure)
Cookie vs Session vs Token
| 特性 | Cookie | Session | Token |
|---|---|---|---|
| 存储位置 | 客户端 | 服务器 | 客户端 |
| 安全性 | 低 | 高 | 中 |
| 容量 | 4KB | 无限制 | 取决于实现 |
| 跨域 | 受限 | 受限 | 支持 |
| 服务器压力 | 小 | 大 | 小 |
HTTPS
HTTPS = HTTP + SSL/TLS
HTTPS工作流程
1. 客户端发起HTTPS请求
2. 服务器返回证书(包含公钥)
3. 客户端验证证书
4. 客户端生成对称密钥,用公钥加密发送
5. 服务器用私钥解密,获得对称密钥
6. 后续通信使用对称密钥加密SSL/TLS握手
客户端 服务器
│ │
│────── ClientHello ───────────>│
│ │
│<─── ServerHello + Certificate ─│
│ │
│── ClientKeyExchange ─────────>│
│ │
│── ChangeCipherSpec ──────────>│
│ │
│<── ChangeCipherSpec ──────────│
│ │
加密通信HTTP vs HTTPS
| 特性 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 安全性 | 明文传输 | 加密传输 |
| 速度 | 快 | 慢(加密开销) |
| SEO | 一般 | 更好 |
| 证书 | 不需要 | 需要 |
HTTP/2
主要特性
1. 二进制协议
- HTTP/1.1是文本协议
- HTTP/2是二进制协议,更高效
2. 多路复用
- 一个连接并发处理多个请求
- 解决HTTP/1.1的队头阻塞问题
HTTP/1.1:
请求1 ──┐
请求2 ├──> 连接1
请求3 ──┘
HTTP/2:
请求1 ─┐
请求2 ─┼──> 连接1(并发)
请求3 ─┘3. 头部压缩
- 使用HPACK算法压缩头部
- 减少传输数据量
4. 服务器推送
- 服务器主动推送资源给客户端
客户端请求 index.html
服务器推送 style.css、script.jsHTTP/3
主要特性
- 基于QUIC协议(UDP)
- 解决TCP队头阻塞
- 更快的连接建立
- 更好的移动网络支持
HTTP版本对比
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 传输协议 | TCP | TCP | QUIC(UDP) |
| 多路复用 | ❌ | ✅ | ✅ |
| 头部压缩 | ❌ | ✅ | ✅ |
| 服务器推送 | ❌ | ✅ | ✅ |
| 队头阻塞 | ✅ | 部分解决 | ✅完全解决 |
RESTful API
REST原则
- 资源(Resource):URL表示资源
- 统一接口:使用HTTP方法操作资源
- 无状态:每个请求独立
- 可缓存:支持缓存机制
RESTful设计
GET /users # 获取用户列表
GET /users/:id # 获取单个用户
POST /users # 创建用户
PUT /users/:id # 更新用户
PATCH /users/:id # 部分更新用户
DELETE /users/:id # 删除用户最佳实践
使用名词而非动词
- ✅
GET /users - ❌
GET /getUsers
- ✅
使用复数形式
- ✅
/users - ❌
/user
- ✅
使用HTTP状态码
- 200:成功
- 201:创建成功
- 400:客户端错误
- 404:资源不存在
- 500:服务器错误
版本控制
/api/v1/users/api/v2/users
过滤、排序、分页
GET /users?age=25&sort=created_at&order=desc&page=1&size=20
💡 提示
这是一个demo文档,欢迎补充更多HTTP相关内容。