JSON、表单、图片三类接口:先定“客户端怎么判定成功”,再定响应体
一句话回答
三类端点的差别不在 JSON 好不好看,而在客户端判定成功的信号顺序:JSON 依赖状态码与可解析体,表单类依赖状态码与 Location,图片类依赖 Content-Type 与字节完整性。规范应先写清判定顺序与失败时的可读错误,再谈字段命名。
三类端点的响应规范,最容易写偏的地方是从“返回什么字段”开始。更稳的顺序是反过来:先规定客户端按什么顺序判定这次调用成功,再规定成功体和错误体长什么样。同一套字段命名套在 JSON、表单提交和图片下载上,冲突几乎都出现在判定环节,而不是字段环节。
先定判定顺序:状态码 → Content-Type → 响应体#
建议把判定写成一条明确的三步链,并写进文档,而不是留给客户端猜:
- 状态码决定大类:2xx 进入成功分支,4xx 归因到调用方,5xx 归因到服务端。不要在 200 里塞业务失败标记,否则中间层(网关、重试、监控)无法按状态码统计成败。
- Content-Type决定解析器:
application/json走 JSON 解析,text/html或application/x-www-form-urlencoded走表单路径,image/*走字节流。不要靠 URL 后缀或请求参数推断。 - 响应体决定细节:只有前两步通过,才去读字段或写文件。
这条链的价值在于:任何一步失败都能给出确定的处理动作,而不是“解析失败就当前端出错”。
三类端点的成功形态#
| 端点类型 | 成功信号 | 常见错误做法 |
|---|---|---|
| JSON | 2xx + application/json + 可解析的对象 | 200 返回 {"code":500},状态码失去意义 |
| 表单提交 | 303 或 302 + Location,或 2xx 返回 HTML 结果页 | 成功后再返回一份 JSON,浏览器端无法直接消费 |
| 图片/文件 | 2xx + 明确的 image/png 等类型 + 正确字节数 | 出错时返回 200 + 一张“默认图”,调用方无法区分 |
表单类要注意 Location 的语义:它表示“去这里看结果”,不表示“资源已创建”。若确实新建了资源,201 更准确;但浏览器表单场景普遍用 303 转向结果页,这属于约定,不是强制。
二进制端点:错误必须是可读的#
图片接口最难处理的是失败。字节流一旦开始写出,就很难回头改状态码。可落地的约定是:
- 在写第一个字节之前完成校验(鉴权、参数、资源是否存在),失败就返回 JSON 错误体加非 2xx 状态码,并带
Content-Type: application/json。 - 成功响应带
Content-Length,让客户端能判断下载是否被截断;分块传输时用其他完整性手段。 - 不要用占位图冒充成功。如果业务上必须给图,就明确写成“降级图”字段或独立参数,让调用方可选、可识别。
下面是一个错误响应的结构示意,未执行示例,仅说明形态:
HTTP/1.1 404 Not Found
Content-Type: application/json
{"error":{"type":"not_found","message":"image id 不存在","request_id":"YOUR_REQUEST_ID"}}
request_id 是演示占位,实际字段名与是否提供需以接口文档为准。
缓存与内容协商的边界#
三类端点的缓存策略不应统一:
- JSON:多为用户态数据,倾向
Cache-Control: no-store或短时长,并按Vary标注影响响应的请求头。 - 图片:内容确定后可按 URL 做长缓存,配合
ETag支持条件请求;变体(尺寸、格式)应体现在 URL 或Vary中,避免同一地址返回不同内容。 - 表单结果页:通常不缓存,避免回退时看到过期结果。
一份最小规范清单#
- 写明每个端点的成功判定顺序,以及每步失败时的处理动作。
- 错误体统一字段:类型、可读消息、请求标识;不要混入本地化文案以外的业务分支判断依据。
- 声明是否可能返回 3xx,以及客户端是否应跟随重定向。
- 声明内容协商支持的范围(如
Accept不支持时的行为)。 - 对二进制端点单独写“写入前校验”的边界。
核实边界#
本文不涉及 API.PLUS 具体端点的实际行为、字段名、限流与计费规则:本次没有可用的接口文档或发布说明,这些细节待核实,请以官方文档为准。文中 HTTP 语义表述(状态码、Content-Type、Location、Vary 的含义)参照 HTTP 规范的一般定义,本次未附来源链接,建议对照 RFC 9110 原文确认。代码与响应示例均为未执行的形态示意,不作为实测结果。