摘要

  • HTTP/1.0 已把 204 定义为请求完成、但没有新信息需要显示;用户代理不应离开发起请求的文档视图。
  • “No Content” 不等于“没有状态”或“没有元数据”。当前语义规定,响应头描述操作之后的目标资源与选定表示;PUT 成功后,ETag 可指向刚保存的新表示。
  • 204 在头字段结束处终止,不能含内容或 trailers,当前 HTTP 还禁止 Content-Length。空不是格式偏好,而是精确的消息边界。

成功不一定要换一张页面

早期 Web 很容易把两件事连在一起:操作结束,然后返回一个新文档。检索内容时这很自然,结果本身值得展示时也很合理。但“保存并继续编辑”需要另一种成功。

编辑器不必为了证明保存而重新下载整份文档,也不应被确认页面赶出工作面。真正有用的结果很小:动作完成了,新的版本身份在这里,请继续。

204 为这种结果提供了独立类型。它不是正文意外丢失的 200,而是明确声明没有额外内容可送的成功。

因此,它分开了两种权力:服务器改变资源,用户代理决定是否更换当前表示。

HTTP/1.0 把界面连续性写进协议

1996 年 5 月的 RFC 1945 说,204 表示请求已经完成,但没有新信息返回。若客户端是用户代理,它不应改变生成请求的文档视图。

规范主要想到脚本与其他动作:输入可以生效,而活动文档不用离开。响应仍可通过实体头携带新元信息,并把它应用到当前视图中的文档。

两层含义从一开始便同时存在。没有正文不会削弱“已完成”;当前页面留下也不是浏览器偶然没有动作,而是预期行为。

HTTP/1.0 同时规定,204 不得包含消息正文。

HTTP/1.1 把终点固定在空行

RFC 2068 在 1997 年保留这一模型,并明确 204 没有 message-body,响应在头字段后的第一行空行结束。

1999 年的 RFC 2616 进一步说明:服务器已经完成请求,无须返回实体正文,但可以返回与所请求变体相关的更新元信息。用户代理应保留视图,并把信息应用到它。

方法定义把 204 放在执行之后。DELETE 已生效且无结果表示时可返回 204;PUT 成功修改已有资源时,可以用 200 返回结果表示,也可以用 204 不返回。

正文缺失没有让操作退回“仍待处理”。提交边界已经越过。

204 不是零字节的 200

空 200 和 204 的内容字节数都可能是零,但两者不做同一承诺。

普通 200 通常预期有内容,即使消息框架把长度标成零。204 表示成功结果不需要额外响应内容。状态码为缺席给出理由,也决定通用组件的框架和界面假设。

客户端不必猜测某个本应到来的表示是否丢失;服务器也不能一边声明 204,一边偷偷附上状态文档。

零可以是一项数据。204 是一项控制结论。

头字段描述的是操作后的世界

2014 年的 RFC 7231 把时间指向说得更清楚:204 的元数据属于请求动作应用之后的目标资源与选定表示。

PUT 示例尤其重要。若成功 PUT 收到带 ETag 的 204,这个 ETag 标识目标资源的新表示。编辑器无须重新下载刚保存的内容,就能更新本地版本标记。

正文没有出现,结果身份仍然存在。Date、缓存控制与其他适用字段仍可提供事实。若客户端因为“204 什么也没有”而丢弃全部头字段,就会失去下一次条件保存所需的证据。

ETag 也不能被想当然地绑定到请求载荷;它描述源站处理后的选定表示。

页面留在原处,但本地知识可以前进

保留文档视图不等于把它冻结在旧状态。服务器假定用户代理会用自己的界面提示成功,并把新元数据应用到活动表示。

源站控制是否完成以及哪些操作后元数据具有权威。用户代理控制如何提示、是否需要再读一次资源。

这样可以省掉两次不必要的迁移:服务器不回显整份文档,客户端不进入确认页。与此同时,ETag 可以让并发控制状态继续前进。

屏幕没有移动,本地模型不必因此陈旧。

205 规定了相反的界面分支

HTTP 205 Reset Content 同样不带内容,却要求用户代理重置发起请求的文档视图,为下一次输入恢复原始状态。

204 没有这种要求。保存场景中,文档应继续可编辑。若把 204 当作 205,可能清空字段、丢掉上下文或移动焦点,而服务器从未要求这些动作。

所以“都是无正文成功”并不是完整分类。内容缺席相同,界面控制不同。

把所有无正文状态映射到一个通用 UI 分支,会抹掉协议最有价值的区别。

202 位于另一侧的时间边界

HTTP 202 Accepted 也可能很短,但它只表示处理被接受,尚未完成,最终还可能不执行。

HTTP 204 表示请求已经成功完成。因为没有正文就重试,可能重复早已生效的动作;在异步工作尚未结束时返回 204,则会谎报提交时点。

这对付款、删除、发布以及任何不可随意重复的动作都重要。正文长度不能证明完成,状态码才能。

一个空响应可能在提交之前,也可能在提交之后。202 与 204 说明它站在哪一边。

头字段就是完整响应

当前 RFC 9110 规定,204 在头字段结束处终止,不能包含内容或 trailers,服务器也不得发送 Content-Length。

严格边界保护持久连接。如果语义上不允许内容的响应后出现意外字节,不同解析器可能给出不同解释,或把这些字节与下一条消息混淆。

自动添加 JSON、换行、追踪尾部或 Content-Length: 0 的中间件必须理解状态。头字段结束,响应已经结束。

“无内容”的意义由下一条消息允许从哪里开始来保证。

启发式可缓存没有取消方法规则

RFC 7231 说 204 默认可缓存;RFC 9110 更精确地称其“heuristically cacheable”,除非方法或显式控制另有规定。

这不意味着任意 POST、PUT、DELETE 响应都可存储并用于随后请求。RFC 9111 仍把存储和复用绑定到方法、缓存键、新鲜度与控制指令。

可能被保存的往往是操作后元数据,而非不存在的正文。在错误上下文中复用,会把 ETag 或策略状态附到另一项动作。

源站应给状态变更响应发送有意的缓存控制,中间缓存必须保留方法意识。

有时“没有内容”确实太少

只有客户端无需结果表示也能正确继续时,204 才合适。业务动作可能产生必要的标识符、收据、恢复令牌、冲突说明或下一步 URI。

把这些结果藏在 204 后面不是简洁,而是应用契约不完整。HTTP 允许无内容,并不让所有省略都正确。

若界面需要规范化后的资源,用户代理仍可重新获取。204 只说本响应不要求换页,不禁止后续读取。

最小传输成立的前提,是缺少的字节真的重复。

IANA 保存的是一种精确缺席

IANA HTTP 状态码注册表 把 204 No Content 指向 RFC 9110 第 15.3.5 节。

动作成功,没有额外响应内容,元数据描述操作后的资源,当前视图无需被替换,消息在头字段后结束。

这些都不表示资源为空、不存在或已删除;不表示头字段可以忽略;也不要求重置界面。

名称很短,缺席的边界却非常具体。

保存完成了,却没有夺走屏幕

204 是一种克制。源站知道动作已完成,却不通过确认页面控制用户的下一视图。用户代理仍负责本地反馈与继续工作。

克制不是模糊。状态固定完成,头字段固定身份,消息框架固定终点。

每层保留自己的权限:服务器保存,客户端留下,元数据前进,网络停止。

页面不变,是因为协议没有更多内容要展示,而不是因为什么也没发生。