📡 HTTP 协议基础
HTTP 请求方法完全指南
9 种请求方法的定义、特征、代码示例和使用场景,一页讲透。
📊 速查总表
| 方法 | 含义 | 安全 | 幂等 | 请求体 | 缓存 | 频率 |
|---|---|---|---|---|---|---|
| GET | 读取资源 | ✅ | ✅ | 无 | ✅ | ★★★★★ |
| POST | 创建资源 | ❌ | ❌ | 有 | ❌ | ★★★★★ |
| PUT | 完整替换 | ❌ | ✅ | 有 | ❌ | ★★★☆☆ |
| PATCH | 部分更新 | ❌ | ⚠ | 有 | ❌ | ★★★★☆ |
| DELETE | 删除资源 | ❌ | ✅ | 通常无 | ❌ | ★★★★☆ |
| HEAD | 只取头部 | ✅ | ✅ | 无 | ✅ | ★★☆☆☆ |
| OPTIONS | 查询能力 | ✅ | ✅ | 无 | ⚠ | ★★★☆☆ |
| CONNECT | 建立隧道 | — | — | 无 | ❌ | ★☆☆☆☆ |
| TRACE | 诊断回显 | ✅ | ✅ | 无 | ❌ | ★☆☆☆☆ |
安全(Safe):只读操作,不修改服务器数据。 幂等(Idempotent):执行 1 次和执行 100 次结果相同。 ⚠ 表示取决于具体实现。
📖 逐一详解
GET
从服务器获取资源。是最常用的请求方法,用于读取数据。
核心特征
- ▸可以缓存(浏览器、CDN)
- ▸参数通过 URL 查询字符串传递(`?key=value`)
- ▸请求体通常为空
- ▸幂等:多次相同请求结果一致
- ▸可被书签收藏
代码示例
// 获取用户列表
fetch('/api/users')
.then(res => res.json())
.then(data => console.log(data))
// 带查询参数
fetch('/api/users?page=1&limit=10')🎯 典型场景:获取博客文章列表、查看用户详情、搜索商品
POST
向服务器提交数据,用于创建新资源或执行某个操作。
核心特征
- ▸数据放在请求体中(JSON / 表单 / 文件)
- ▸不会被缓存(默认)
- ▸非幂等:多次相同请求可能创建多条记录
- ▸常见 Content-Type:application/json、multipart/form-data
- ▸HTML <form> 默认使用 POST
代码示例
// 创建新用户
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: '张三',
email: 'zhangsan@example.com'
})
})🎯 典型场景:注册账号、提交表单、上传文件、发表评论
PUT
完整更新一个资源。客户端需要提供资源的全部字段。
核心特征
- ▸幂等:多次相同请求结果一致
- ▸通常需要提供资源的完整数据
- ▸如果资源不存在,可能创建新资源
- ▸与 POST 不同:PUT 指定了资源的完整 URL
- ▸RESTful API 中 PUT /users/1 表示更新 ID=1 的用户
代码示例
// 完整替换用户 ID=1 的所有信息
fetch('/api/users/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: '李四',
email: 'lisi@example.com',
role: 'admin'
})
})🎯 典型场景:更新用户全部资料、替换文章全文、设置配置项
PATCH
部分更新一个资源。只发送需要修改的字段,不修改的字段保持不变。
核心特征
- ▸非幂等(通常,但可以实现为幂等)
- ▸只传需要修改的字段,节省带宽
- ▸比 PUT 更灵活、更常用
- ▸JSON Patch(RFC 6902)定义了标准补丁格式
- ▸实际开发中 PATCH 使用频率远高于 PUT
代码示例
// 只更新用户的邮箱,其他字段不改
fetch('/api/users/1', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'newemail@example.com'
})
})🎯 典型场景:修改密码、更新头像、修改邮箱、部分更新文章
DELETE
删除指定资源。操作通常不可逆,使用时需谨慎。
核心特征
- ▸幂等:多次删除同一个资源结果一致(已删除)
- ▸请求体通常为空
- ▸一般需要身份验证和权限校验
- ▸返回 200(带响应体)或 204(无内容)
- ▸部分 API 使用软删除(标记为已删除而非物理删除)
代码示例
// 删除用户 ID=1
fetch('/api/users/1', {
method: 'DELETE',
headers: { 'Authorization': 'Bearer token_here' }
})
// → 204 No Content(删除成功,无返回数据)🎯 典型场景:删除账号、取消订单、移除文章、清空购物车
HEAD
与 GET 完全相同,但服务器只返回响应头,不返回响应体。用于检查资源是否存在、获取元数据。
核心特征
- ▸只返回 HTTP 头,无响应体
- ▸用于检查文件大小(Content-Length)
- ▸用于验证缓存是否过期(Last-Modified / ETag)
- ▸用于检查资源是否存在(200 vs 404)
- ▸节省带宽,不需要下载完整内容
代码示例
// 检查文件是否存在以及大小
fetch('/files/report.pdf', { method: 'HEAD' })
// → Content-Length: 2048576
// → Content-Type: application/pdf🎯 典型场景:检测文件是否存在、获取文件大小、缓存验证、链接有效性检查
OPTIONS
询问服务器支持哪些 HTTP 方法。是 CORS 预检请求的核心,浏览器在跨域请求前自动发送。
核心特征
- ▸CORS 预检:浏览器自动发送,无需手写
- ▸返回 Allow 头:列出支持的 HTTP 方法
- ▸不会触发业务逻辑
- ▸用于 API 文档自动发现
代码示例
// 查询 /api/users 支持哪些方法
fetch('/api/users', { method: 'OPTIONS' })
// → Allow: GET, POST, DELETE, OPTIONS🎯 典型场景:CORS 预检请求、API 能力探测、调试跨域问题
CONNECT
建立到目标服务器的隧道。主要用于 HTTPS 代理,客户端通过代理连接目标服务器。
核心特征
- ▸用于 HTTPS 代理(SSL/TLS 隧道)
- ▸WebSocket 升级代理有时也会用到
- ▸浏览器自动使用,开发者很少手动调用
- ▸建立双向通信隧道
代码示例
// 浏览器通过代理访问 HTTPS 网站时自动使用
// 开发者通常不需要手动调用 CONNECT
// 代理收到 CONNECT example.com:443 后建立隧道🎯 典型场景:HTTPS 代理、企业网络代理、VPN 类工具(开发者很少手动使用)
TRACE
回显服务器收到的请求。用于诊断:查看请求在传输过程中被代理服务器做了哪些修改。
核心特征
- ▸服务器原样返回收到的请求
- ▸用于调试代理链和中间件
- ▸有安全风险:可能泄露 Cookie 和认证信息
- ▸大多数服务器默认禁用
- ▸一般只在内网调试时使用
代码示例
// 诊断代理是否修改了请求头
fetch('/api/debug', { method: 'TRACE' })
// → 服务器回显收到的完整 HTTP 请求内容🎯 典型场景:调试代理链、诊断请求篡改、内网故障排查(生产环境通常禁用)
🔑 三个关键概念
🛡️
安全(Safe)
请求只读取数据,不修改服务器上的任何资源。GET 和 HEAD 是安全的。安全方法可以被搜索引擎爬虫安全地访问。
🔄
幂等(Idempotent)
同一个请求执行 1 次和执行 100 次,服务器的最终状态相同。GET、PUT、DELETE 都是幂等的。POST 不是幂等的。
💾
缓存(Cacheable)
响应能否被浏览器或 CDN 缓存。GET 和 HEAD 可缓存。POST 默认不可缓存。缓存可以大幅减少服务器压力和加载时间。
🏗️ RESTful API 最佳实践
将 HTTP 方法和 URL 路径结合,可以设计出清晰直观的 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 的用户
核心原则:URL 代表"资源"(名词),HTTP 方法代表"动作"(动词)。