代表性面试主题

后端面试:代理改写响应时,如何正确使用 HTTP 203?

后端困难
Offer.cc 编辑团队发布 更新

题干

一个网关会对源站响应做恶意软件过滤或格式转换。什么时候应该返回 HTTP 203,而不是 200、304 或错误码?请说明缓存、ETag、审计和回源策略。

题干与适用场景

你负责一个 API 网关,代理可能过滤恶意附件、移除隐私字段或转码响应。源站请求成功,但下游收到的表示已经不是源站原样。请说明何时返回 203、如何更新缓存验证器、怎样避免客户端把代理内容误当成权威源站数据。

HTTP 203 是成功响应,表示转换代理修改了源站 200 响应的头字段或内容。它适合需要把“已成功但经过中间层改写”显式传给客户端的场景,不应被当作通用错误码或权限拒绝码。

面试官考察点

  • 能否准确区分 203、200、304、4xx 和 5xx 的语义。
  • 能否说明转换代理为何影响缓存、ETag、签名和后续请求。
  • 能否设计原始表示与转换表示的审计关联。
  • 能否处理多层代理重复转换、回源失败和客户端不理解 203。
  • 能否把协议语义落到可测试的响应头与缓存行为。

回答前需要澄清的问题

  1. 改写是安全过滤、压缩转码还是个性化字段移除?它决定是否仍可共享缓存。
  2. 客户端能否识别 203?若不能,网关是否要保守返回 200 并在自有元数据中说明转换?
  3. 原始内容是否需要可追溯?签名、ETag 和审计记录必须绑定原始与转换版本。
  4. 转换是否确定性?相同源站版本若因规则不同产生不同表示,缓存键必须包含规则版本。

30 秒回答框架

我先确认网关是否真的改变了成功响应的内容或头字段。若源站成功且代理改写了表示,可用 203 明确告知客户端;未改写则保留 200。203 不代替 304,304 只表示客户端缓存仍可使用。转换后重新计算适用于下游表示的 ETag,避免复用源站校验器;缓存键加入内容协商、规则版本和租户边界。审计记录同时保存源站版本、转换规则和输出摘要,回源失败仍按实际失败语义返回。

分步骤深入解答

1. 先建立状态码边界

200 表示当前响应成功,未声明中间层改变了表示;203 表示请求成功但转换代理修改了源站 200 的头字段或内容;304 不携带新表示,只告诉客户端复用已验证缓存。过滤失败、权限拒绝和回源超时分别使用对应的 4xx 或 5xx 语义。

2. 识别转换类型

恶意附件替换链接、隐私过滤、格式转码和镜像标记都可能形成 203。只改变传输层压缩或 hop-by-hop 头通常不应宣称应用表示被改写。网关要在内部记录“源站表示”和“下游表示”的差异。

3. 重新处理验证器

源站的 ETag 描述源站表示,转换后的实体应生成新的、只对下游表示有效的 ETag。若转换是按规则版本决定的,规则版本必须进入缓存键或 ETag 计算输入;否则规则升级后客户端可能错误复用旧结果。

4. 设计缓存和协商

Vary、内容编码、语言、租户和过滤规则都会影响可共享性。对含用户隐私的转换结果默认私有缓存;对公共、确定性转换可共享,但要限制缓存范围。收到下游 If-None-Match 时,网关应针对自己的转换表示验证,不能直接把源站 304 透传给已改变的下游表示。

5. 保护签名与审计

若源站签名覆盖原始字节,改写后该签名不能继续证明下游内容。网关应明确签名主体,必要时重新签名或删除不再有效的签名头。审计事件记录源站请求 ID、源 ETag、规则版本、输出 ETag、转换原因和操作者。

6. 处理多层代理

多个代理可能连续转换。每层都要避免覆盖前一层的审计关联,并在转换不具幂等性时停止重复处理。若下游不理解 203,协议适配层可以返回 200,但必须通过文档化扩展头或专用元数据暴露转换状态,不能悄悄丢失安全信号。

7. 验证与回滚

测试源站 200、代理改写后 203、未改写 200、客户端缓存命中 304、规则升级、回源超时和过滤器失败。回滚规则时验证新旧 ETag 不冲突,并检查缓存中是否仍存在由旧规则生成的共享对象。

高质量示范回答

我会把 203 当作“成功,但转换代理改变了源站表示”的协议声明。源站成功且没有应用层改写时返回 200;改写了内容或相关头字段时返回 203;304 只用于验证下游已有表示,不能因为源站返回 304 就忽略转换层。网关为转换后的表示重新生成 ETag,并把规则版本、内容协商和隐私边界纳入缓存键。源站签名若覆盖原始字节,改写后必须重新签名或移除。每次转换记录源 ETag、规则版本和输出摘要,测试 200/203/304、规则升级、多层代理和回源失败,确保客户端不会把过滤后的内容当成源站原文。

常见错误

  • 所有代理响应都返回 203 → 语义失真且影响客户端处理 → 只有成功且表示确实被改写时使用。
  • 继续复用源站 ETag → 下游验证器对应错误表示 → 为转换结果重新计算 ETag。
  • 把 203 当错误码 → 客户端可能重试或告警 → 失败使用真实的 4xx/5xx 语义。
  • 透传源站 304 → 转换层可能跳过必要的重新验证 → 针对下游表示验证缓存。
  • 忽略规则版本 → 规则升级后命中旧缓存 → 规则版本加入缓存键或验证器。

追问及应对

代理只改了 Content-Encoding,是否需要 203?

通常不需要。传输编码属于传输层处理;若没有改变应用层表示,保留 200,并按 HTTP 缓存规范处理编码协商。

203 响应可以被共享缓存吗?

可以,但前提是转换确定、缓存键包含所有变化维度,并且内容没有用户隐私。租户或用户相关过滤应使用私有缓存。

源站返回 203,网关又改写一次怎么办?

保留两层转换的关联,重新计算最终表示的 ETag,并确保规则具备幂等性;无法保证时只允许一次转换或拒绝重复处理。

客户端只接受 200,是否把 203 改成 200?

可以在明确的兼容层做,但要附带可识别的扩展元数据并记录降级。不能静默隐藏安全过滤或隐私改写。

回源返回 304,但本地没有转换后的缓存对象怎么办?

不能直接返回 304。网关需要取回可用表示、重新执行转换,或返回能反映缺少本地表示的失败结果。

公开来源

同类题目