Skip to main content

API 错误应该返回什么

·1 min

现在前后端沟通的方式大多应该是基于 http 的序列化使用 json 的请求, 规范往往会使用 Restful. 然而程序大多数时间都是在处理异常, 但是错误信息组织方式却千奇百怪, 这里简单说一下我自己的理解.

有人会说, http 状态码 很多时候已经可以当做错误信息了, 也就是返回 body 可以不包含太多信息, 当然可以这样, 但是当我们的业务如果不只是基于 http, 例如 ws, 基于返回状态码的方式将不再适用, 所以我们应该在初期制定一个较为通用的适合自己的规范.

1. 错误响应类型: #

interface Error {
  code: string
  message: string
  messages?: string[]
}

code 为错误信息码, message 为错误信息详情, messages 为错误信息补充信息(例如: 参数校验错误详情).

也可以加入 statusCode, 适配非 http 请求.

2. 错误响应状态码不该为 2xx: #

如果使用过一些流行的 http cliet 库, 例如 JSaxios, 就会了解到 非2xx 的请求会被当做 error catch 到. 因为一般来说 2xx 的含义是正常响应, 也就是说流程可以正常进行, 因此我们应该让客户端拿到 2xx 的时候可以自信得走正常流程.

相对的, 有些人喜欢只要服务端不挂, 响应状态码都会是 200, 数据格式是这样的:

interface Response {
  ok: boolean
  data: any
  error: any
}

也就是无论如何, 客户端都需要先检查 ok 字段或者 error 字段. 这样做会带来一些问题, 首先返回会在正常响应中冗余额外数据; 其次有时候可能会失误导致 ok 和 error 不一致; 最主要是客户端没办法做到信任, 一些全局的错误处理也没法做(比如: catch 到 401 跳到登录页).

3. code 应做到含义清晰唯一: #

code 一般会作为客户端收到 error 之后第二个检查的字段(第一个为 statusCode). 所以我们应该尽可能多得将信息传递给客户端.

一般建议 code 类型使用 string 常量, 除非觉得状态码比较隐秘, 可以使用数字, 通过内部状态对照表查看, 但是使用数字时, 要避免和 http 状态码 重复.

其次, 错误码应该做到全局唯一, 也就是不要出现相同的错误码在不同的接口下含义不一, 这样会造成很多开发者负担以及维护负担.

还有, 错误码应为常量, 绝对不能将多语言做在错误码中.

4. message 应当简洁明了: #

message 作为错误码的补充, 应当简洁明了, 某些时候其实是不必要的, 有些时候也可以用作客户端显示信息.

5. messages 应当尽可能包含全部信息: #

messages 作为最后一个属性, 需要包含剩下的所有信息, 最常用的就是用作显示参数校验错误详情.

6. 尽可能得少暴露服务端状态: #

对于 5xx 的错误, 或者预期之外的错误, 应当尽可能得少暴露信息, 不要返回任何详情.