1. 题目与使用场景
设计一个 REST API:客户端可以查询列表、更新资料和删除资源。面试官要求你解释为什么某些成功请求返回 200,另一些返回 204,以及空列表、找不到资源和成功删除分别应该如何表达。假设客户端依赖稳定的 JSON 契约,并且网关会记录响应体大小。
2. 面试官考察点
- 是否理解 204 的核心约束是成功且没有消息体,而不是“结果为空”。
- 是否能把资源表示、集合语义和客户端解析行为放在同一个契约里讨论。
- 是否知道 RFC 9110 对 204 的缓存与元数据规则,能说明 ETag 等响应头仍可有价值。
- 是否能给出 200、204、404 的可预测选择,而不是死记某个方法的固定状态码。
3. 回答前需要澄清的问题
- 请求是否成功改变了资源,还是读取一个集合的表示?
- 客户端是否需要新的 JSON 表示、分页元数据或下一步链接?
- “没有结果”代表合法的空集合,还是目标资源不存在?
- DELETE 的幂等语义和重复删除的产品契约是什么?
4. 30 秒回答框架
先判断成功响应是否需要携带表示:需要 JSON、分页信息或资源状态时用 200;操作成功且客户端不需要消息体时用 204。列表查询得到合法空集合仍返回 200 和 [],因为集合表示存在;单个目标不存在才考虑 404。DELETE 常用 204,但若要返回删除后的审计信息或统一信封,就用 200。最后说明禁止在 204 中发送消息体,并测试客户端对两种成功响应的处理。
5. 分步骤深入解答
第一步:区分“空表示”和“无表示”
200 表示请求成功并允许返回表示。GET /users?team=none 找到一个合法集合,只是成员数为零,因此返回 200、[] 和分页字段,客户端仍能按列表契约解码。204 表示操作已成功,但响应不包含消息体;它适合不需要新表示的更新或删除确认。
第二步:为写操作选择状态码
PATCH 成功后若客户端需要服务器规范化后的对象、版本号或字段,就返回 200 和资源表示;若客户端只需知道写入完成,返回 204,并可用 ETag 或其他头传递版本元数据。DELETE 成功通常返回 204;如果 API 要返回撤销令牌、审计记录或统一响应信封,则返回 200。两种做法都要在所有端点保持一致。
第三步:处理 404 与重复请求
空列表不是 404,因为集合资源存在。请求具体 /users/42 而资源不存在,才使用 404。对 DELETE 的重复调用,要先定义“已不存在”是否视为成功:若 DELETE 设计为幂等且不泄露资源存在性,可再次返回 204;若业务需要通知客户端对象从未存在,也可以返回 404,但必须记录在契约中。
第四步:验证协议和客户端行为
204 响应不能包含消息体,客户端不得无条件调用 JSON 解析。契约测试应覆盖状态码、Content-Length、响应头和空体;浏览器、SDK、代理和缓存层都要验证。若资源版本通过 ETag 传递,客户端可在后续 If-Match 请求中使用它,而无需把对象表示塞进 204。
6. 高质量示范回答
我先问客户端是否需要新的资源表示。需要对象、分页字段或统一 JSON 信封时返回 200;操作完成但没有内容要交给客户端时返回 204,并确保响应没有消息体。合法的空列表仍是 200 加 [],因为集合存在;具体资源不存在才是 404。PATCH 可以在需要服务器规范化结果时返回 200,否则返回 204 并带 ETag。DELETE 通常用 204,但如果要返回审计信息就用 200。最后用契约测试确认客户端不会对 204 调 JSON 解析,并明确重复 DELETE 的产品语义。
7. 常见错误
- 把“列表为空”返回 204 → 客户端失去统一的数组和分页契约 → 返回 200 与空集合表示。
- 在 204 响应中放 JSON 信封 → 违反无消息体约束且不同代理处理不一致 → 移除响应体或改用 200。
- 认为 DELETE 永远必须是 204 → 忽略审计信息或规范化结果的需求 → 根据是否需要表示选择 200 或 204。
- 把所有空结果当成 404 → 混淆集合存在与成员不存在 → 先判断请求目标是集合还是具体资源。
- 客户端对所有 2xx 都调用 JSON 解析 → 204 会触发解析异常 → 按状态码分支处理并增加契约测试。
8. 追问及应对
追问一:GET 查询没有匹配项,可以返回 204 吗?
技术上可以表示无内容,但会破坏列表端点的统一形状。只要查询本身成功且集合存在,优先 200 加空数组和分页元数据;只有契约明确把“无表示”作为结果时才用 204。
追问二:204 可以带 ETag 吗?
可以。204 没有消息体,但响应头仍可携带资源版本等元数据。客户端可以保存 ETag,在下一次条件更新中发送 If-Match,从而避免为传递版本而返回完整对象。
追问三:重复 DELETE 应该返回 204 还是 404?
取决于幂等和信息披露策略。若“删除后目标状态就是不存在”且不需要区分首次与重复调用,可以稳定返回 204;若调用方必须知道资源是否曾存在,则返回 404。选择应固定在 API 契约,不要按实现路径随机变化。