公开 API 错误模型与重试策略
公开 API 的客户端必须同时判断 HTTP 结果、响应格式和业务字段。一个 HTTP 200 不一定代表业务成功;一个网络超时也不一定代表服务端没有完成写入。
本文只覆盖网页和公开客户端可见的接口行为,不描述服务内部实现。
三层结果
第一层:传输结果
先读取:
- HTTP 状态码;
Content-Type;- 响应体是否为空;
- 请求是否在客户端超时。
文件下载接口可能返回图片或 JSON 错误,不能对所有响应无条件调用 json()。
第二层:通用业务结果
多数 JSON 写入接口使用:
{
"success": true,
"msg": "success"
}验证 Token 的接口可能使用:
{
"valid": true,
"expires_at": "<RFC3339_TIME>",
"expired": false
}不要只看 msg 是否为英文成功文字。优先判断布尔字段,再把 msg 用于界面提示。
第三层:数据完整性
业务成功后还要确认数据字段:
- 列表字段存在且为数组;
- 分页响应的总数和当前数组可以解释;
data不是意外的null;- 文件接口的内容类型符合预期;
- 写入后重新读取能看到目标值。
例如恢复缓存返回条数,只表示服务处理的条目数量;它不是所有页面都已经完成索引的证明。
HTTP 状态处理
| 状态 | 常见含义 | 客户端动作 |
|---|---|---|
| 2xx | 请求到达服务 | 继续判断业务字段和数据完整性 |
| 400 | 参数缺失或格式错误 | 修正本地输入,不自动重试 |
| 401 | Token 无效或已过期 | 停止后台请求,要求重新登录 |
| 403 | 账号没有当前权限 | 显示权限提示,不猜测其它入口 |
| 404 | 地址或版本不匹配 | 检查基础地址和接口版本 |
| 409 | 当前状态不允许写入 | 重新读取状态后再决定 |
| 413 | 文件或请求过大 | 缩小范围/文件,确认页面限制 |
| 429 | 请求过于频繁 | 使用退避,不并行刷接口 |
| 5xx | 服务暂时异常 | 只对幂等读取有限重试 |
| 其它 | 未知传输结果 | 保留状态码和非敏感消息,停止高风险动作 |
不同部署可能使用不同状态码。表格是客户端分流建议,不是绕过服务规则的依据。
业务失败处理
success: false
把 msg 显示给用户并保留当前本地输入。对于写入接口:
- 不要立刻换参数重试;
- 记录目标字段或索引的脱敏名称;
- 重新读取当前状态;
- 确认失败是否来自权限、格式、状态或网络;
- 只有用户明确确认后再尝试一次。
valid: false
立即停止依赖该 Token 的轮询、写入和上传。清理内存中的 Token,保留本地账号显示条目,要求用户重新验证。不要把旧 Token 传给其它端点测试。
成功但数据不完整
如果业务字段缺失、数组类型不对或文件内容为空,按“响应格式异常”处理。不要把不完整响应保存为新的备份,也不要用它覆盖本地有效缓存。
读取请求的退避
只对不改变服务状态的读取操作使用有限重试:
第一次失败:等待 1 秒并重试一次
第二次失败:等待 3 秒并重试一次
第三次失败:停止,显示错误和时间遇到 401、403、400 或明确业务失败时不等待重试;遇到 429 时优先使用服务要求的等待时间。页面离开后取消未完成的读取,避免后台继续消耗会话。
写入请求的幂等边界
以下操作不能因为超时就自动重复:
- 保存配方;
- 发布评论或回复;
- 上传缓存;
- 删除相片或上传快照;
- 恢复缓存;
- 应用订单、重启、挂载或其它机台动作。
超时后的安全顺序是:重新验证 Token → 读取状态/列表 → 对照目标是否已经生效 → 只在确认未生效且用户同意时重试。
文件响应
一个健壮的文件读取器应先检查:
const response = await fetch(url, options);
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('application/json')) {
const result = await response.json();
// 处理 success/msg
} else if (response.ok) {
const blob = await response.blob();
// 交给图片或文件预览器
} else {
// 记录状态码,不把二进制当 JSON 解析
}下载文件时还要检查空内容、文件名和浏览器下载权限。不要把文件内容自动上传到错误收集服务。
可观测性字段
客户端日志只保留排障所需的最小字段:
时间(含时区)
接口分类和动作
HTTP 状态
业务 success/valid
响应耗时
是否发生重试
脱敏后的账号别名不要记录请求体原文、完整 URL 查询值、Token、密码、访问码、二维码、机台标识、完整 JSON 或图片内容。若必须关联请求,使用客户端生成的随机追踪编号,不要使用凭据本身。
开发环境模拟
开发者可以在本地把以下结果作为测试夹具:
- 200 +
success: true; - 200 +
success: false; - 401 +
valid: false; - 429 + 退避提示;
- 503 + HTML 错误页;
- 200 + 图片二进制;
- 200 + JSON 错误;
- 客户端超时但下一次读取已显示写入成功。
测试夹具中的 Token 和地址必须是占位符。不要用真实聊天记录、真实备份或生产凭据做错误处理测试。
