API 错误应该返回什么
Table of Contents
现在前后端沟通的方式大多应该是基于 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
库, 例如 JS
的 axios
, 就会了解到 非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
的错误, 或者预期之外的错误, 应当尽可能得少暴露信息, 不要返回任何详情.