服务端业务处理不成功,应该返回HTTP 200 还是 HTTP 4XXX系列?

场景

其实,纠结只出现在例如保存表单的场景,如果服务端因各种业务上的原因(校验不通过,状态不满足等)导致保存未成功,并要返回对应的提示信息,此时服务端回应此HTTP 请求时,是用 “200 + json” 还是用“400 + 错误信息”?

在公司内不同项目间,两种风格都有,且小伙伴们各执己见。

我这么看

首先,我先表达我赞同“200 + json”的方式。

更具体些,服务端所有的Controller Method对返回值做统一的Response包装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
样例1
{
"code": 200,
"data": {...},
"message":"操作成功"
}

样例2
{
"success": false
"data": {...},
"code": 100409,
"message":"数据已存在"
}

我的观点

1. 协议分层

对于RPC请求,存在两个层面的操作结果

[1] HTTP请求本身的结果 ———— 业务无关性,与网络、框架层面相关
[2] 业务处理的结果 ———— 强业务逻辑相关性,与网络、框架层面无关

为什么我们会有本贴讨论的话题与分歧,或者说为什么大部分人觉得http code不够试用,是因为实际开发应用场景中,尝试着只用http code 去表达上述两个层面的结果。

分层表示的优点:

  1. 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协议没有的
-------------本文结束感谢您的阅读-------------
谢谢你请我吃糖