在 API 开发或对接中,经常会看到协议中有自定义 code 的设计
- 那为什么要这么设计呢?
- 这种设计有没有什么实践?
- 大厂都是怎么做的呢?
跟随本文,一起揭晓以上问题
为什么还要自定义 code?
HTTP 协议中定义了 5 类 status code
- Informational responses(
100
–199
) - Successful responses(
200
–299
) - Redirection messages(
300
–399
) - Client error responses(
400
–499
) - Server error responses(
500
–599
)
这其中留给开发者可以用的 status code 少之又少,而实际的业务响应又会有非常多的状态,所以开发者需要一种方式来扩展 code。
这其中最直观的方式就是定义一个标准的响应结构,这个结构中有着一个自定义的 code
字段,它可以用来表示业务的响应状态,如下:
{
"code":"A1000",
"message":"会员已过期"
}
所以,自定义 code 本质上是对 status code 的一个扩展,是为了满足实际业务中复杂的状态表达而设计的。
自定义 code 该怎么用?
HTTP 的 status 不够用导致我们设计了自定义 code,但现在很多 API 的 code 都已经被滥用了。
我推荐的做法是:按语义将 HTTP status 当作一级分类,自定义 code 当作二级分类
- 2xx 请求成功
- 4xx 客户端错误,不影响服务可用性
- 5xx 服务端错误,影响服务可用性
2xx 代表成功,实际业务场景下很少会碰到成功之下还要再区分不同的成功状态的,即使遇到了,设计一个更符合业务语义的字段通常也会更好。
所以, 2xx 的响应没必要设置自定义 code
而 4xx、5xx 这种错误响应之下再做错误细分的场景是很常见的,比如 4xx 客户端错误之下需要明确具体的业务错误:支付时用户余额不足、商品库存不足、支付超时等。
现在明确了只为 4xx、5xx 扩展 code,而 code 又是由响应体来承载的,接下来就看看如何设计错误响应体。
错误响应体怎么设计?
先来看看微软在它的 REST API guidlines 里的设计
https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#errorresponse–object
{
"error": {
"code": "BadArgument",
"message": "Multiple errors in ContactInfo data",
"target": "ContactInfo",
"details": [
{
"code": "NullValue",
"target": "PhoneNumber",
"message": "Phone number must not be null"
},
{
"code": "NullValue",
"target": "LastName",
"message": "Last name must not be null"
},
{
"code": "MalformedValue",
"target": "Address",
"message": "Address is not valid"
}
]
}
}
GITHUB 在其 REST API 平台上也有示例
{
"message": "Validation Failed",
"errors": [
{
"resource": "Issue",
"field": "title",
"code": "missing_field"
}
]
}
这里的 code 可以分为以下几类
Error code name | Description |
---|---|
missing | A resource does not exist. |
missing_field | A required field on a resource has not been set. |
invalid | The formatting of a field is invalid. Review the documentation for more specific information. |
already_exists | Another resource has the same value as this field. This can happen in resources that must have some unique key (such as label names). |
unprocessable | The inputs provided were invalid. |
从 GITHUB 和微软的设计上我们可以得出一些规律
- code 是可读的
- 通常也会包含一个详细描述的 message 字段
- 根据响应,调用方有能力定位到导致错误的资源(字段)