前提:前后端定义了通用的数据结构包含 data,mseeage,code,success 这几个基本字段用来去接收后端接口的数据。
场景:某一接口客户端发出的请求出现参数或后端校验等业务错误
问题:后端 http 层的 response code 应该返回什么? 200 还是非 200 ?(呆过的不同公司有着不一样的习惯)
问题来源:主要是用的网络请求框架( retrofit ),对于小于 200 或者大于等于 300 的 response code 直接抛了异常,但我并不想对这异常再进行解析 HttpException 中的 response body 解析出上述的数据结构,所以我拦截了 response 改了 response code 为 200 。这样的话,我对于 response code 无论是什么,我都可以同样的对象解析。
1
kile 2021-10-18 18:51:39 +08:00 3
code 是业务码,是前后端进行约定的东西。不要用和 http code 一致的方式,这样会让人混淆。。
|
2
Jooooooooo 2021-10-18 18:54:36 +08:00 4
0 成功, 去拿 data 中的内容
非 0 异常, 展示 msg 中的内容 |
3
securityCoding 2021-10-18 18:58:08 +08:00
success 没看懂 ,其他三个够用了
|
4
SingeeKing 2021-10-18 19:06:13 +08:00 1
遵从 REST 的应该是 400,不遵从就随缘来。。
|
5
CodeCodeStudy 2021-10-18 19:06:40 +08:00 1
code,用 1 来表示成功,大于等于 1000 的整数表示错误码,之所以用 1 是因为弱类型语言中 1 == true,让人一眼就认为是表示肯定的意思,用 1000 以上的整数是为了避免和 http 状态码混淆
|
6
b1t 2021-10-18 19:13:58 +08:00 via iPhone
我今天也把代码里的大于 300 抛异常给注释掉了,等个讲解
|
7
hingbong 2021-10-18 19:37:06 +08:00 via Android 1
我们是遵循 HTTP 定义,异常都是 4xx 5xx,当然,封装的结构也有详细的错误码
|
8
jerryshao 2021-10-18 19:37:11 +08:00 1
后端参数校验错误应返回 400 HTTP respond code 。
message 应返回有帮助性的错误信息,比如请求参数里的 XXX 字段长度不能超过 YYY 等等。 code 字段可以是自定义错误码,一个自定义错误码对应一个异常。 Retrofit 抛异常是对的,前端应该 catch 这个异常并做相应处理。 比如 catch 异常并分析 respond 是 400,打印日志,看是否需要提示前端用户参数错误或加强表单验证。 如果 catch 异常并分析 respond 是 500,打印日志,上报监控指标,配置 client 进行请求重试。 |
9
hlayk OP @jerryshao 后端返回是没问题 retrofit 抛异常也对。只是后端对于正确与否的数据都是同样的封装 所以 retrofit
将异常给抛出来需要做额外的解析 如果后端返回的是 200 自定义的数据结构 中 code 再指定的话 那样就不需要写额外代码了,我只需解析一次返回对象 针对不同业务 code 做不同的处理 |
10
hlayk OP @securityCoding code 太具体 不够抽象 大部分业务只关心成功 失败最多显示下 message
|
11
JasonLaw 2021-10-18 20:36:04 +08:00 via iPhone 1
|
12
Hyvi 2021-10-18 20:48:18 +08:00 via iPhone 1
非 200 。以后监控更方便搞。自定义的 code 最好自定义的错误。
|
13
IvanLi127 2021-10-18 20:50:27 +08:00 via Android
在 header 传递业务层的 code 。
|
14
jerryshao 2021-10-18 21:24:53 +08:00 1
@hlayk 可以是可以,但是大家在这里建议的是业界比较认可的做法。
如果返回 200,前端根据 code 字段做相关处理,那后端做可用性相关的监控就比较让人头疼。 不知道你们有没有对后端的 canary test,中文好像叫拨测?将来持续测试后端 api 的话,正常来说判断 api 是否成功就是使用这些 http respond code 。如果后端都是返回 200,那相关的测试也无法从 http respond code 获知是否成功,需要解析里面的自定义 code 才知道。 |
15
hlayk OP @jerryshao 是的 我认为后端这样返回是对的 只是我自己代码里加了个拦截器 把所有 response code 都改写成了 200 这样方便自己统一的处理 但是写完感觉怪怪的
|
16
oxromantic 2021-10-18 22:21:56 +08:00 2
想想 http 的 code 有啥作用就能想通怎样用最好
举例来说,http 400 表示错误的请求,404 很多框架表示服务找不到不可达,这些都是属于预期之外的错误,在评估服务健康度的时候都需要采纳,如果混用,譬如把 404 作为常规业务逻辑(离谱点譬如搜索找不到就返回 404 ),就会产生很大的功能混淆,如果再集成一些网络日志框架(听 X 之类),简直就是业务和标准错误混合的灾难 可以参考下百度云 api 的设计,虽然百度云很流氓,但是不可否认 api 定义还是有参考价值的 另外我不同意上面说的持续测试只采用 http response code 来判断,这种属于没经历过 http 时代电信的鞭打以及没用过 cdn,永远不要相信 http response code 能代表你业务的状态,否则就是给项目埋雷 |
17
tiedan 2021-10-18 23:09:34 +08:00
code 返回 200,code 用特定错误代码,网关层写规则根据 code 转换成 4xx or 5xx
|
18
xuanbg 2021-10-19 07:24:01 +08:00
实际上有 success 表示调用是否成功的话,code 基本没啥用。因为你 success 是 false,都直接输出 message 了。有 code 啥事?
|
19
xuanbg 2021-10-19 07:28:10 +08:00
@oxromantic 对的,http response code 只能代表 API 服务本身的状态,而不能代表 API 服务上的业务的状态。把这两个状态混起来用虽然也能用,但遇到问题就很难定位到底是哪个层面的问题了。
|
20
yidinghe 2021-10-19 08:04:56 +08:00 via Android
协议层的问题和业务层的问题不要混淆吧,不然的话例如前端得到 404,可能是后端框架因为配置错误根本没将请求转发给业务层,会给排查带来不便
|
21
Rache1 2021-10-19 09:27:37 +08:00
看前端,可以让前端传个指定 header 来给所有响应都返回 200,默认按照 HTTP CODE 返回。
实际 response 里面的 code,我之前的做法都是三位 HTTP CODE + 三位业务 CODE 。 比如 400001,400 就是对应 HTTP CODE 中的请求参数有问题,001 就是可能是某个字段或者某个过程没有校验通过。 |
22
2i2Re2PLMaDnghL 2021-10-19 10:19:56 +08:00 1
作为 Web 实质标准的 JavaScript,其 Fetch API 对于 4xx 5xx 都不抛错,你换个正常点的请求框架吧。
有人说,并不一定非得用 HTTP status code 才叫 RESTful,甚至不一定需要 HTTP 另外,我不推荐 "success": true/false,而采用 "status": "OK"/"NOT_FOUND"/... ,这样塞更多的实质状态比较方便。 不要用「码」,用「符号」。码是在计算机性能不足的情况下的妥协,符号才是正统。 @yidinghe 这个问题本应当可以快速地从 404 text/html 还是 404 application/json 区分出来 |
23
oxromantic 2021-10-19 11:05:41 +08:00
@2i2Re2PLMaDnghL retrofit 你居然让换个正常点的框架?类似 ios 的 alamofire,都是 top1 的框架,都不建议在非 200 的 http status code 里处理业务逻辑
|
24
hlayk OP @oxromantic 大家又不是都是搞移动端的 不知道这些库也正常
|
25
abcbuzhiming 2021-10-19 11:40:44 +08:00
关于 code 返回什么,一直有争议,有人认为就应该用 http 的 status code,所以他们返回 200 ;而另外一群人比如我就认为 code 是业务码,和 http status 无关,正常下就是 0,非 0 就是错误,并且附带错误信息 msg 。
|
26
lewinlan 2021-10-19 12:55:17 +08:00 via Android
业务内的异常就装在 code 里,http 给 200 。
网络,框架等非业务的异常,才用 400/500 的 http 。 把资源装进 data,这个事情就已经不 REST 了 |
27
2i2Re2PLMaDnghL 2021-10-19 13:01:28 +08:00
@oxromantic 这个建议是为了 HTTP 以外的一些协议没有 status code 所以将 HTTP 降级。这就好比因为很多网站不支持 bbcode 就要求现在在用 bbcode 的网站一律不允许使用 bbcode 一样可笑。
|
28
oxromantic 2021-10-19 13:46:39 +08:00
@2i2Re2PLMaDnghL 你搞错了,这些 status code 并不是你应用独占的,和容器抢这些 status code,就会给前端引入不确定性的混乱,而没有个前端定义一个可以直接判断属于业务数据的基础规则
|
29
2i2Re2PLMaDnghL 2021-10-19 14:26:06 +08:00
@oxromantic 那就更诡异了,容器为什么要抢 status code ?它连 HTTP 都不 aware
|
30
penll 2021-10-19 14:30:42 +08:00
code 直接英文字母,方便后端定位问题。
message 只是给用户看得友好信息 |
31
oxromantic 2021-10-19 16:04:21 +08:00
@2i2Re2PLMaDnghL pcf/k8s 都会啊,可以了解下
|
32
unco020511 2021-10-19 16:45:27 +08:00
两种都可以,看你们怎么理解,可以把 http 单纯当做一个数据传输协议,只要数据传输成功一律 httpcode200,然后定义自己的业务 code.同时因为 httpcode 也是语义化的,也可以使用仅使用 httpcode 一套来表示传输及业务状态
|
33
ychost 2021-10-19 17:50:52 +08:00
code 建议用字符串,这样方便两个调试,httpCode 一律 200
|
34
2i2Re2PLMaDnghL 2021-10-20 09:40:23 +08:00
@oxromantic 首先,PCF 似乎是 VMWare 的多个不同的东西的品牌名称?具体没搜到。k8s 是编排工具而不是容器。
其次,各类 load balancer 看上去也并不会抢 status code,而是尝试中间捕获 status code 来判断服务健康状况来安排重启和替换请求,这种情况下会修改的可不止是 status code,而是整个响应都会被替换。 |
35
xingheng 2021-10-20 13:27:32 +08:00
@Jooooooooo #2 我要是看见谁用 0 标识自定义 code 为成功的话一定往死里骂,int 的默认值(在很多语言里很多都)是 0,本来就是取个 int 的事情非要我区分到底是因为服务器本身返回的傻逼 0 还是 code 值取不到用了 int 默认值。
|
36
oxromantic 2021-10-20 13:55:27 +08:00
@2i2Re2PLMaDnghL pcf 是比较早的商业容器实现,大概被 vmware 收购了,具体没了解,既然你提到整个响应都会被替换,这就是我之前描述的场景,你以为的业务 response,实际已经被替换了,所以不能光靠 http status code 来处理业务,还需要加额外的逻辑,但既然加额外的逻辑,何必还抱死 http status code ;另外,我所谓的容器是广义的,譬如远古的 war 跑在 tomcat 里,那么 tomcat 就是 war 的容器,tomcat 自己也会用到 http status code 表达自己的状态
|
37
Jooooooooo 2021-10-20 14:45:16 +08:00
@xingheng 你担忧的问题在这里不是问题. 用了就知道.
|
38
2i2Re2PLMaDnghL 2021-10-20 15:42:22 +08:00
@oxromantic 替换应是对前端透明的,不需要额外逻辑。
Tomcat 算是混合了一个编排工具? 编排工具如何返回它自身的信息应当是可以自定义的,而不是埋暗雷(但暗雷见得多了,Flask 也暗雷)。不过现在问题是科技树还没点到动态编译语言。 当然,如 #26,放 data 已经不 REST 了,本来的处理上就是 body 就是全部内容或者没有内容,甚至,尽管不那么典型,这个 URL 逻辑上是可以 cd 进去的(类似 WebDAV )。 应当将这种状态和其他协议的 code/data 状态进行对应。gemini 更诡异一点( |
39
xingheng 2021-10-20 16:34:24 +08:00
@Jooooooooo #37 不是所有语言都支持 optional type,后端写的接口需要考虑各种语言的使用场景。
|
40
bthulu 2021-10-20 17:11:09 +08:00
非对外公开给其他部门或其他公司使用的 API,一律不做任何处理,什么 status, code, msg 都不需要,逻辑成功就返回对象,失败就返回异常信息。前端框架统一对 4XX 错误做下处理,其余什么也不要做。简单就是美
|
41
zachlhb 2021-10-21 08:10:26 +08:00 via iPhone 1
http code 永远返 200,然后错误码用自己数据的 code 区分,为什么不用 http code,因为一些前端框架拿不到非 200 的响应数据,非 200 响应在前端来看就是异常,直接走前端框架的异常处理了
|
42
bug123 2021-10-21 08:11:13 +08:00
0 表示成功
非 0 表示错误码,message 作为额外的补充 |
43
hlayk OP @zachlhb 是的 问题就在这里 返回的响应结果本身就是同一个数据结构 但是因为 http code 非 200 导致框架抛出异常 我这里就需要额外捕获异常 再从异常中解析 response 这在我这里看来就是多此一举 但是我也没有合适的理由去说服后端去改 http code 所以加了拦截器 将后端所有的 http code 改为了 200 以便统一处理
|
44
flyingfz 2021-10-21 11:19:07 +08:00
http 协议相关 的状态码, 交给 status code . 例如 无权限 403, 找不到资源 404,参数错误 400 之类.
业务的状态码交给 code, 例如登陆失败, 扣款失败。注意, 此时 status code = 200 . |