首页/网络/协议速查/If-Match 匹配前置条件
HTTP 头与缓存70 条

If-Match 匹配前置条件

条件请求头:仅当资源的当前 ETag 与给出值匹配时才执行;用于防止并发覆盖(乐观锁)。

协议速查网络更新于 2026-10-13

If-Match 是什么

If-Match 是条件请求头:客户端把自己上次读到的 ETag 带上,服务器只有在当前资源的 ETag 与之匹配时才执行这次写操作,否则返回 412 Precondition Failed。这是 HTTP 层的乐观锁——两个人同时编辑同一条记录时,后提交的人会收到 412,从而避免「后来者静默覆盖前者」的数据丢失。

基本信息

方向请求头
取值ETag 列表,或通配符 "*"
比较方式强校验:弱 ETag(W/ 前缀)不参与匹配
不匹配时返回 412 Precondition Failed
规范RFC 9110 §13.1.1
配合头ETag、If-None-Match、428 Precondition Required

典型使用场景

  • 文档协作或配置管理:防止并发编辑互相覆盖
  • 订单状态流转:确保读取到的是同一个版本再更新
  • 幂等写入保护:只在资源未被改动时才覆盖,避免重放请求破坏数据
  • 用 If-Match: * 表达「资源必须已存在」,否则视为失败
  • 服务端用 428 强制要求客户端带条件头,杜绝无条件的覆盖写

乐观锁更新流程

乐观锁更新流程
# 1) 先读取资源并记下 ETag
ETAG=$(curl -sI https://api.example.com/docs/7 | awk 'tolower($1)=="etag:"{print $2}' | tr -d '\r')
# 2) 带条件提交更新,只有版本一致才会成功
curl -si -X PUT https://api.example.com/docs/7 \
  -H "If-Match: $ETAG" -H 'Content-Type: text/markdown' \
  --data-binary @doc.md
# 3) 版本已被他人改动 → 服务端返回 412,客户端应重新拉取合并

响应与处理

服务端行为返回码客户端应做什么
ETag 匹配,更新成功200 或 204更新本地缓存的 ETag
ETag 不匹配412 Precondition Failed重新获取资源,合并后再提交
缺少 If-Match 而服务端要求428 Precondition Required改为带条件头重试
资源不存在404 Not Found确认路径或先创建资源
使用弱 ETag 做匹配412(强校验不通过)改用强 ETag 或去掉 W/ 前缀
If-Match 用的是强校验:带 W/ 前缀的弱 ETag 不能用于匹配,因为弱 ETag 只保证语义等价、不保证字节一致,用它做并发控制会漏掉真实的冲突。
如果服务端只支持 If-Match 但客户端默认不带条件头,那么并发覆盖依然会发生。真正的防线是服务端返回 428 强制要求条件头,而不是依赖客户端自觉。

易错点

  • 用弱 ETag(W/ 开头)做 If-Match 匹配:强校验直接判定失败,表现为「明明没改过却总是 412」
  • 收到 412 后不做合并直接重试同一份数据,会把别人的修改覆盖掉,乐观锁形同虚设
  • 服务端计算 ETag 时把易变字段(如访问计数、时间戳)算进去,导致 ETag 频繁变化、冲突率虚高
  • 把 If-Match 当成权限校验手段:它只保证版本一致,不具备任何鉴权能力

数据来源与参考

  • RFC 9110 §13.1.1 If-Match
  • RFC 9110 §8.8.3 ETag

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌