场景
其实,纠结只出现在例如保存表单的场景,如果服务端因各种业务上的原因(校验不通过,状态不满足等)导致保存未成功,并要返回对应的提示信息,此时服务端回应此HTTP 请求时,是用 “200 + json” 还是用“400 + 错误信息”?
在公司内不同项目间,两种风格都有,且小伙伴们各执己见。
我这么看
首先,我先表达我赞同“200 + json”的方式。
更具体些,服务端所有的Controller Method对返回值做统一的Response包装
1 | 样例1: |
我的观点
1. 协议分层
对于RPC请求,存在两个层面的操作结果
[1] HTTP请求本身的结果 ———— 业务无关性,与网络、框架层面相关
[2] 业务处理的结果 ———— 强业务逻辑相关性,与网络、框架层面无关
为什么我们会有本贴讨论的话题与分歧,或者说为什么大部分人觉得http code不够试用,是因为实际开发应用场景中,尝试着只用http code 去表达上述两个层面的结果。
分层表示的优点:
- RPC请求, 是可以基于不同的底层协议的, 比如我们用的HTTP协议,很容易替换成ZeroMQ, RabbitMQ, UDP, 基于TCP的自定义协议…… 只要能实现一问一答模型的协议,都是可以用的。这个时候, HTTP协议只是一种底层协议, 底层协议的错误号,并不应该被上层协议使用。
2. HTTP Code 表达能力局限性
虽然HTTP协议非常友好的定义了诸多的HTTP Code码,但在实际开发应用中,对于繁多的应用场景,HTTP Code的表达能力显得力不从心,部分场景仍旧不能避免的辅以Response Body信息。加之这些HTTP Code并不是应用开发中的绝对标准。
3. HTTP Code 语义表达的不统一性
[1] 同样是HTTP 4XX系列,不同系统的解释也是不一样的
[2] 同样是”参数校验不通过”的业务问题,不同系统使用的HTTP码也是不一样的
4. Http Code数量有限,表达能力有限
这个应该很好理解,大家应该也有体会。
5. 系统集成友好性
如果我们把HTTP协议当作一种传输层协议看待,200 可以很好表达, 整个底层传输都是没有问题, 包括负载均衡系统, nginx, 反向代理, fast cgi守护程序都是工作正常的。
而返回各种HTTP Status Code经常会让外部使用者非常的困惑,特别是他们对HTTP Status Code有一定了解,却对你的系统不甚了解的情况下。
所以,除了考虑ajax请求的处理,还要考虑整个调用的中间链路以及框架集成方面的因素
- 返回200能避免CDN等中间商替换或缓存
- 国内的通信运营商画蛇添足根据HTTP状态码给替换成导航页或广告推广页面
- 对于系统审计程序不友好,例如 HTTP Response Code = 4XX的请求算请求成功?请求失败?请求异常?————无法区分!
6. 扩展性
- 返回200OK,扩展性更强,修改的时候只需要修改字段而不需要特别处理Status Code
- 易于与真正的400错误区分,方便审计和分析。而实际上,当服务器能够正常返回,证明服务器已经正确的理解并得出相应的结果(并且这个结果也是预定义的,并非未知),这显然与400的定义不符。
- 返回200更优。保不准哪天某种状态是HTTP协议不支持的,保不准哪个需要新增的字段是HTTP协议没有的