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