GET vs POST:有什么区别?(2026)
关于 HTTP GET 和 POST 方法的清晰解释及实用示例
开始使用 Hypereal 构建
通过单个 API 访问 Kling、Flux、Sora、Veo 等。免费积分开始,扩展到数百万。
无需信用卡 • 10万+ 开发者 • 企业级服务
GET vs POST:有什么区别? (2026)
GET 和 POST 是两种最常用的 HTTP 方法,理解何时使用它们是 Web 开发和 API 设计的基础。本指南将通过代码示例、对比表及实际应用指导,清晰地解释两者之间的区别。
快速对比
| 特性 | GET | POST |
|---|---|---|
| 目的 | 获取数据 | 发送/创建数据 |
| 数据位置 | URL 查询字符串 (query string) | 请求体 (request body) |
| 可见性 | 数据在 URL 中可见 | 数据在请求体中隐藏 |
| 缓存 | 默认可缓存 | 默认不可缓存 |
| 可收藏为书签 | 是 | 否 |
| 浏览器历史记录 | 参数会被保存 | 参数不会被保存 |
| 数据长度 | 有限制(URL 限制约 2,048 字符) | 无实际限制 |
| 幂等性 | 是(相同请求 = 相同结果) | 否(可能创建重复数据) |
| 安全性 | 是(不应修改数据) | 否(会修改服务器状态) |
| 后退按钮 | 安全重新执行 | 浏览器会在重新提交前提示警告 |
| 编码 | application/x-www-form-urlencoded |
支持多种类型 |
GET 如何工作
GET 请求从服务器检索数据。参数作为查询字符串在 URL 中发送。
示例:获取用户数据
GET /api/users?page=1&limit=10&sort=name HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer token123
服务器响应请求的数据:
{
"users": [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
],
"total": 42,
"page": 1,
"limit": 10
}
GET 代码示例
JavaScript (fetch):
// 简单 GET 请求
const response = await fetch('https://api.example.com/users?page=1&limit=10');
const data = await response.json();
// 带请求头
const response = await fetch('https://api.example.com/users?page=1', {
method: 'GET',
headers: {
'Authorization': 'Bearer token123',
'Accept': 'application/json'
}
});
Python (requests):
import requests
# 简单 GET
response = requests.get('https://api.example.com/users', params={
'page': 1,
'limit': 10,
'sort': 'name'
})
data = response.json()
# params 字典会转化为: /users?page=1&limit=10&sort=name
cURL:
curl -X GET "https://api.example.com/users?page=1&limit=10" \
-H "Authorization: Bearer token123" \
-H "Accept: application/json"
何时使用 GET
- 获取项目列表(用户、产品、文章)
- 通过 ID 加载单个资源 (
/users/42) - 执行搜索查询 (
/search?q=python+tutorial) - 过滤和分页 (
/products?category=electronics&page=2) - 任何不会更改服务器上数据的操作
POST 如何工作
POST 请求向服务器发送数据,通常用于创建新资源或提交信息。数据在请求体中发送,而不是在 URL 中。
示例:创建用户
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer token123
{
"name": "Charlie",
"email": "charlie@example.com",
"role": "developer"
}
服务器响应创建的资源:
{
"id": 43,
"name": "Charlie",
"email": "charlie@example.com",
"role": "developer",
"createdAt": "2026-02-06T10:30:00Z"
}
POST 代码示例
JavaScript (fetch):
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
body: JSON.stringify({
name: 'Charlie',
email: 'charlie@example.com',
role: 'developer'
})
});
const newUser = await response.json();
Python (requests):
import requests
response = requests.post('https://api.example.com/users', json={
'name': 'Charlie',
'email': 'charlie@example.com',
'role': 'developer'
}, headers={
'Authorization': 'Bearer token123'
})
new_user = response.json()
cURL:
curl -X POST "https://api.example.com/users" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
-d '{
"name": "Charlie",
"email": "charlie@example.com",
"role": "developer"
}'
何时使用 POST
- 创建新资源(用户、订单、评论)
- 提交表单数据(联系表单、登录表单)
- 上传文件
- 触发特定操作(发送电子邮件、处理支付)
- 发送敏感数据(密码、令牌/Token)
- 任何会更改服务器上数据的操作
核心区别详解
1. 数据位置
GET 通过 URL 的查询参数发送数据:
https://api.example.com/search?query=javascript&page=1
POST 通过请求体发送数据:
POST /search HTTP/1.1
Content-Type: application/json
{"query": "javascript", "page": 1}
这一点很重要,因为 URL 会被记录到日志、缓存、存储在浏览器历史记录中,并且在地址栏可见。敏感数据绝不应放入 URL。
2. 幂等性 (Idempotency)
GET 是幂等的: 连续发送 10 次相同的 GET 请求会产生相同的结果。获取 /users/42 始终返回用户 42(假设数据未被独立更改)。
POST 不是幂等的: 连续发送 10 次相同的 POST 请求可能会创建 10 个重复的资源。向 /orders 提交相同的数据可能会产生 10 张相同的订单。
# GET: 允许重试,是安全的
for _ in range(10):
response = requests.get('/api/users/42') # 始终返回用户 42
# POST: 在没有防护措施的情况下重试是危险的
for _ in range(10):
response = requests.post('/api/orders', json=order_data) # 会创建 10 个订单!
这就是为什么当你刷新一个通过 POST 加载的页面时,浏览器会发出警告。
3. 缓存 (Caching)
GET 响应默认会被缓存(被浏览器、CDN 和代理服务器缓存)。这使重复请求变得飞快,但可能导致数据过时问题。
POST 响应默认不会被缓存。每次请求都会发送到服务器。
# GET: 第二个请求可能来自缓存
requests.get('/api/products') # 从服务器获取
requests.get('/api/products') # 可能返回缓存后的响应
# 若要防止缓存,可添加随机参数或请求头
requests.get('/api/products', headers={'Cache-Control': 'no-cache'})
4. 数据大小限制
GET 受限于最大 URL 长度。虽然 HTTP 规范没有定义限制,但浏览器和服务器通常会执行以下限制:
| 浏览器/服务器 | URL 长度限制 |
|---|---|
| Chrome | ~2 MB (实际建议 ~8,000 字符) |
| Firefox | ~65,536 字符 |
| Safari | ~80,000 字符 |
| Internet Explorer (旧版) | 2,083 字符 |
| Apache | 8,190 字符 (默认值) |
| Nginx | 8,192 字符 (默认值) |
| IIS | 16,384 字符 (默认值) |
POST 对请求体大小没有实际限制。你可以发送兆字节级别的数据、上传文件或大型 JSON 负载。
5. 安全性 (Security)
从本质上讲,GET 和 POST 都不是绝对“安全”的——两者都需要 HTTPS 加密。然而,它们在安全性方面存在重要差异:
GET 参数会暴露在:
- 浏览器地址栏
- 浏览器历史记录
- 服务器访问日志
- Referrer 请求头
- 浏览器书签
- 代理服务器日志
POST 请求体数据:
- URL 中不可见
- 不存储在浏览器历史记录中
- 不包含在 Referrer 请求头中
- 仍可能在服务器日志中可见(如果服务器记录了请求体)
- 在网络工具中依然可见(除非使用 HTTPS)
# 错误做法:在 URL 中传输密码 (GET)
GET /login?username=alice&password=secret123
# 正确做法:在请求体中传输密码 (POST)
POST /login
Content-Type: application/json
{"username": "alice", "password": "secret123"}
# 真正的安全性都需要搭配 HTTPS
常见错误
错误 1:使用 GET 修改数据
# 错误:GET 不应该修改数据
@app.route('/api/users/42/delete', methods=['GET'])
def delete_user():
db.delete_user(42)
return {'status': 'deleted'}
# 正确:使用 DELETE 或 POST 进行数据修改
@app.route('/api/users/42', methods=['DELETE'])
def delete_user():
db.delete_user(42)
return {'status': 'deleted'}
为什么这很重要:网络爬虫、浏览器的预取机制以及代理服务器可能会自动访问 GET 链接。如果你的 GET 接口用于删除数据,那么爬取你网站的 GoogleBot 可能会删光你的整个数据库。
错误 2:通过 GET 发送敏感数据
# 错误:API 密钥泄露在 URL 中(各处都会留痕)
requests.get('/api/data?api_key=sk-secret-key-12345')
# 正确:将 API 密钥放在 Headers 中
requests.get('/api/data', headers={'Authorization': 'Bearer sk-secret-key-12345'})
错误 3:未处理 POST 重复提交
# 错误:没有防重保护
@app.route('/api/orders', methods=['POST'])
def create_order():
order = db.create_order(request.json)
return order
# 正确:使用幂等键 (Idempotency Keys)
@app.route('/api/orders', methods=['POST'])
def create_order():
idempotency_key = request.headers.get('Idempotency-Key')
if idempotency_key:
existing = db.get_order_by_idempotency_key(idempotency_key)
if existing:
return existing
order = db.create_order(request.json, idempotency_key=idempotency_key)
return order
除 GET 和 POST 之外:其他 HTTP 方法
GET 和 POST 最为常用,但 HTTP 还为特定操作定义了其他方法:
| 方法 | 目的 | 是否幂等 | 示例 |
|---|---|---|---|
| GET | 读取数据 | 是 | GET /users/42 |
| POST | 创建数据 | 否 | POST /users |
| PUT | 替换全部数据 | 是 | PUT /users/42 |
| PATCH | 局部更新数据 | 否* | PATCH /users/42 |
| DELETE | 删除数据 | 是 | DELETE /users/42 |
| HEAD | 仅获取请求头(无内容) | 是 | HEAD /users/42 |
| OPTIONS | 获取支持的方法 | 是 | OPTIONS /users |
*PATCH 可以被实现为幂等,但规范并不强制要求。
RESTful API 设计模式
| 操作 | HTTP 方法 | 端点 (Endpoint) | 请求体 |
|---|---|---|---|
| 获取所有用户 | GET | /api/users |
无 |
| 获取单个用户 | GET | /api/users/42 |
无 |
| 创建用户 | POST | /api/users |
用户数据 |
| 更新用户 | PUT | /api/users/42 |
完整用户数据 |
| 部分更新 | PATCH | /api/users/42 |
仅需更改的字段 |
| 删除用户 | DELETE | /api/users/42 |
无 |
| 搜索用户 | GET | /api/users?name=alice |
无 |
常见问题解答 (FAQ)
我可以在 GET 请求中发送 Request Body 吗? 技术上可以,但强烈不建议。许多服务器、代理和库会忽略或剔除 GET 请求体,有些甚至会直接拒绝。GET 数据应使用查询参数。
POST 比 GET 更安全吗? 并非天生如此。POST 只是在 URL 栏和浏览器历史中隐藏了数据,但如果没有 HTTPS,两者在网络上都是以明文形式传输的。安全性必须始终使用 HTTPS。
登录表单应该使用 GET 还是 POST? 始终使用 POST。你绝不希望用户名和密码出现在 URL、浏览器历史或服务器访问日志中。
什么时候应该用 PUT 而不是 POST? 当服务器决定资源 URL(例如:自动生成 ID)时,请使用 POST。当客户端指定要创建或替换的确切资源位置时,请使用 PUT。
GraphQL 呢?它所有操作都使用 POST。 GraphQL 通常对所有操作(查询和变更)都使用 POST,因为查询语句可能过长,不适合放在 URL 中。对于 GraphQL API 来说这是一个有效的设计选择,尽管某些实现也支持对 Query 使用 GET。
总结
核心规则很简单:使用 GET 读取数据,使用 POST 写入数据。GET 请求绝不应修改服务器状态,敏感数据绝不应放入 URL。
除此之外,请记住 GET 是可缓存且幂等的(重试安全),而 POST 则不然。对两者都要使用 HTTPS,为关键的 POST 接口实现幂等键,并遵循 RESTful 规范以实现整洁的 API 设计。
如果你正在构建处理 AI 生成内容的 API,免费试用 Hypereal AI —— 无需信用卡。其 REST API 遵循同样的 HTTP 规范,让你能轻松地将图像和视频生成功能集成到应用程序中。
