DEBUG.WIKI
雨云;给项目一台云服务器
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关

Got 收到 Retry-After: 0,为什么没有立即重试

Retry-After 为零与 Got 用零表示停止重试容易混淆。区分 413 的退出路径、429 的退避及正式 16.1.0 的最小非零计时处理。

服务端返回 Retry-After: 0,Got 却直接抛 HTTPError,或仍等了一段退避时间才重试。先记录 HTTP 状态码、实际 Got 版本以及 retry 配置;这两种现象不一定走同一条分支。

Retry-After 的零秒表示无需等待。Got 的重试延迟计算中,返回数值 0 又表示停止重试。如果版本实现没有把这两种含义分开,改大 retry.limit 也不一定有用。

413 与 429 的旧行为不同

正式 Got 15.0.0 和 16.0.0 用 if (retryAfter) 判断是否采用服务端等待时间。数值 0 不满足这个条件,接着进入状态码处理:413 会返回 0 并结束重试;429、503 等符合其他重试规则的响应,则可能进入普通指数退避。

所以,不能把“带 Retry-After: 0 的所有响应都零次重试”当成统一结论。还应检查请求方法是否允许重试、状态码是否在列表里、次数是否耗尽,以及应用的 calculateDelay 有没有主动返回零。

正式 16.1.0 将立即重试表示为至少 1 毫秒

16.1.0 判断的是 retryAfter !== undefined,在通过方法、错误或状态码和次数检查后,将允许的零等待转成 Math.max(1, retryAfter)。这样既保留“零表示退出”的内部约定,也让服务器要求的立即重试进入实际定时器。

它仍会先比较 maxRetryAfter 或请求时限形成的等待上限;不能为了让一次 413 重试成功,就删除时限、扩大所有状态码,或覆盖全部重试规则。1 毫秒只是最小计时值,实际调度不保证精确在一毫秒后发生。

实际升级前确认 Node 22 或更新、ESM 及项目依赖兼容。若项目已经自定义 calculateDelay,应特别检查迁移后是否仍把合法的 computedValue 改回 0。不要用一个永远返回 1 的函数覆盖它,那可能让本来不该重试的请求进入额外尝试。

用实际尝试次数判断是否恢复

在可控制的只读接口上分别核对 Retry-After 为 0、正数、HTTP 日期以及缺失时的行为,并分别覆盖 413 和 429。保留总时限和有限次数,统计真正到达服务器的请求,不能只看最终 Promise 是成功还是失败。

如果暂不能升级,服务端由自己管理且业务允许等待,可以按接口策略返回一个合适的正数秒值,避开旧版的零值分支;这会实际增加等待时间,不是完全等价的立即重试。不要改写不受自己管理的上游响应,或让应用无限重发有副作用的写请求。

错误由 413 变成成功响应,也只证明该次重试流程完成。原来的请求体大小限制、服务端幂等性和业务是否已经处理,都要按接口契约判断,不能由 Retry-After 推断。