API错误码规范
文章目录
做了这么多年项目,倾听了太多开发人员对API接口返回错误码的吐槽,收到了太多用户对系统中云里雾里错误信息的埋怨。我在这几年实践中尝试过一些的解决方案,今天就做一下总结。
错误码应考虑因素
- 给用户展示的信息,友好、温馨、易懂的措辞
- 给客户端开发者排查定位的信息,包含准确细节,如exception信息、stacktrace等,方便程序定位和处理
- 错误码详细信息,如:错误码url展示网页,包括错误定义、产生原因、解决办法等
- 给服务端开发者排查定位的信息,如错误唯一id,服务端开发人员可以根据此id定位到该次请求的所有相关log。
在具体实践中,建议使用HTTP Status为主,错误码code为辅的设计方案,以下是我曾尝试过的三种错误码规范。
自定义规范
一般会使用一个枚举类来统一定义系统中所有的错误码,然后自定义错误处理,例如github的规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Headers: Content-Type: application/json;charset=UTF-8 X-RateLimit-Limit: 3000 X-RateLimit-Reset: 1503162176432 X-RateLimit-Remaining: 0 { "message": "Message title", "errors": [ { "code": "rate_limit_exceeded", "message": "Too Many Requests. API rate limit exceeded", "document": "https://developer.github.com/v3/gists/" } ] } |
Spring规范
在spring中,只需要抛出异常,spring会自动转换为如下格式
1 2 3 4 5 6 7 |
{ "timestamp": "2018-11-31T03:43:50.881+0000", "status": 500, "error": "Internal Server Error", "message": "No message available", "path": "/v3/test/1" } |
Problem+json规范
简介
采用problem+json格式我们可以让错误输出更具有描述性,可以让API消费者更好进行错误处理,其核心是如下几个字段:
1 2 3 4 5 |
type: 提供一个描述问题的连接(required) title: 对错误做一个简短的描述(required) status: HTTP status code(required) detail: 详细的人可理解的错误信息(optional) instance: 返回错误产生的URL, 绝对地址(optional) |
相关规范和实现:
示例
1 2 3 4 5 6 7 8 9 10 11 12 |
HTTP/1.1 403 Forbidden Content-Type: application/problem+json Response Body: { "type": "https://example.com/probs/out-of-credit", "title": "You do not have enough credit.", "detail": "Your current balance is 30, but that costs 50.", "instance": "/account/12345/msgs/abc", "balance": 30, "accounts": ["/account/12345", "/account/67890"] } |
推荐实践
错误码最大问题不在规范,而是在执行,也就是说一开始错误码定义都是非常美好,但是经过一段时间的开发后,错误码总是在往坏的方向不断累积。所以对于一个小的团队,建议直接采用Problem/Problem+json规范,这样团队成员在执行上,不会太排斥。
由于Problem/Problem+json规范中唯一定位一个错误的是type,没有code,可以做一下小的改进或约束,比如将title当错误码code,另外对于其他字段比如时间戳、服务端错误日志定位等可以使用自定义扩展字段。