现有状况
发现很多RESTful API的错误代码都是用HTTP的状态码(Status Code)作为API的错误代码,公司的一些产品也是如此,如下图所示:
这种设计基本是把错误代码依次映射到HTTP的状态码上,HTTP协议中定义的状态码基本包含下面几类:
- 1xx Informational
- 2xx Success
- 3xx Redirection
- 4xx Client Error
- 5xx Server Error
比如对一个常见的新增用户的API,返回的Code会设计如下:
- 201 创建成功
- 400 请求错误(验证不通过,输入错误)
- 401 操作未授权
- 409 用户已存在
这种设计虽然可以覆盖大多数的情况,但对于一些业务逻辑错的话,就没有对应的HTTP状态码匹配了。比如,新增用户的时候,发现用户组人数已经达到上限了,给一个什么样的状态码呢?或者发现数据库无法访问了,又给一个什么状态码呢?
HTTP状态码是HTTP协议的一部分,应用层的API是不应该知道下层协议的细节的。假如有其他的业务错误无法对应上现有的HTTP状态码,岂不是还的自己扩展出更多的状态码?这样也会导致HTTP状态码和业务耦合,无论是服务端还是客户端。
设计方案
我的设计方案是,所有RESTful Web Service返回结果的结构都相同,不考虑改变HTTP返回的状态吗,而只是在返回结果中表明状态和错误信息,大致结构如下:
{success:true|false, data:[]|{} [, error_code:, error_message:] }
通过success字段来表明这个请求的成功或失败;如果成功,则可以读取data数据进行后续处理;如果失败,可以读取error_code和error_message进行错误的处理。这样的好处就是,既不用关心HTTP状态码,也不用对成功或失败来处理不同的JSON结构。
一些常见的设计
- Facebook
自定义错误代码,HTTP状态码统一为200。
{
“error”: {
“message”: “(#803) Some of the aliases you requested do not exist: me1”,
“type”: “OAuthException”,
“code”: 803
}
} - 新浪
使用自定义错误代码,错误的HTTP状态码是400。 http://open.weibo.com/wiki/Error_code - 腾讯
使用自定义错误代码,错误的HTTP状态码统一是200。
http://wiki.open.qq.com/wiki/%E5%85%AC%E5%85%B1%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E - 阿里巴巴
自定义错误代码,不需要关心HTTP状态码
{
“error_code”:“450”,
“error_message”:“Required argument memberId : expect [type: java.lang.String]“,
“exception”:“Required argument memberId : expect [type: java.lang.String]”
}