📡 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 方法代表"动作"(动词)。