为什么后端开发都喜欢自己定义 responseCode? HTTP 状态码不够用吗?

2020-05-29 14:10:45 +08:00
 watanuki

所有请求都返回 200,然后自己定义 responseCode, 好像很多大厂的后端接口都是在这样做的,这样做有什么好处? 现在后端开发是不是已经有了关于 responseCode 的统一标准?还是一个公司一套标准? 如果没有统一标准,大家在开发个人的后端项目时也会用 responseCode 吗?

26314 次点击
所在节点    程序员
216 条回复
pushback
2020-05-29 18:30:34 +08:00
我的开发习惯是要处理参数错误 http 那边响应 400 没问题,但是才 responseCode 这里我会返回 400.01~400.99 来标明参数错误的原因
no1xsyzy
2020-05-29 18:33:55 +08:00
@Vegetable #62 前端处理业务逻辑本身,而不需要再研究 404 究竟是 URL 拼错了还是没有这个对象。
这句话我同意,但问题在于,没有这个对象难道不应该是 400 ? null 对象不能进行 GET 操作(开个玩笑)

其实你想象中的很多问题,大部分都应该让自动化测试和配置反哺解决的,就比如 URL 拼错问题,RESTful 中提到,API 返回另一个内容时应当采用 URL 而不是 id 。比如 users?{query} 应当得到的是形如 ["/users/alice", "/users/bob"],而每一个用户的 URL 则应由路由生成,比如 Flask 有 url_for,错也错得一致,反而没什么问题,Don't Repeat Yourself 。
再不济也是由 CI 和 unit test 捕获。
如果这层都漏了漏到用户侧去了,返回 404 还是返回 400 都没什么差别。我远在接受编程相关知识之前就长期各种折腾极限情况,发生这种情况我只能意识到 “我对此无能为力”,用户侧拿到的信息再多也等于没有。如果已经是你自己跑测试了,那就不存在 trace 能解决而 debugger 不能解决的问题。
colorfulberry
2020-05-29 18:43:06 +08:00
用户看到的所有错误都是网络错误哈哈哈。
no1xsyzy
2020-05-29 18:46:24 +08:00
@sunny352787 #90 我看我没有人身攻击,如果你觉得有哪句让你觉得被冒犯了还请指出(让我见识见识你有多玻璃心
至于你,“就这智商讨论个屁” 这是不是人身攻击呢?我且当它不是,以保持与您继续讨论的氛围。
一来,有一个算一个,认认真真用 “智商” 这个词的,不是坏就是蠢。如果你不知道的话,我且当您犯了一点点正常人都会犯的小蠢;不过我想指出,“智商” 一词是焦虑营销中生搬硬套的概念,原本为了研究青少年大脑发育而发明这个词的那个人都受不了,在 Medium 上发文章指出了这点( https://medium.com/incerto/iq-is-largely-a-pseudoscientific-swindle-f131c101ba39 )。
至于 “不得已而为之的解决方案”,我疑惑您的中文、英文和工科都是谁教的?“不得已而为之” 的不叫 “解决方案”,这仨学科里都应该讲过。
Varobjs
2020-05-29 18:48:59 +08:00
月经贴了
freakxx
2020-05-29 18:49:52 +08:00
这个问题在 V 站讨论挺多次了,

说实话,感觉偏颇说一句,挺丑的。

http code 按实际情况返回
业务需要,在 response 里面再做一层 response code 区分场景
RRRoger
2020-05-29 18:52:13 +08:00
@blessyou #96 原文:“不同模块的错误码分成 100xxx , 200xxx, 300xxx 比较好排查”
======
回复:+1 这个没毛病
no1xsyzy
2020-05-29 19:13:22 +08:00
HTTP 为什么要状态码?这是为了标记 “续延”,是为了能够让客户端正确地应对这一值而作出不同的响应的。
比如,为什么要返回 3xx ?是为了能够让客户端知道,接下来需要根据 Location 头进行跳转了。
为什么要返回 1xx ?是为了让客户端知道发生了一些协议层面上的 meta 改变。
为什么要返回 4xx 和 5xx ?是为了让浏览器正确地理解异常状态的发生,并据此进行恰当的重试,或者不应重试。
总体上来说,逻辑上大致是这样:

what_then = continuation_vector[response.status_code]
what_then(response)

它几乎等价于回调函数的偏移量。

而无论业务码还是扩展 HTTP 状态码都是没必要的,就 HTTP 那些足够了,大部分 CRUD 项目甚至只需要三个,一个 404 一个 200 一个 302,也就有些情况需要个 101,但多半不是我手写的 101 。
第一,现在的 UI,能够在发送请求前对数据作大部分验证。诸如 “这一字段必须是字符串表示的 decimal” 这种提示你一个应用从上线到废弃都不一定会显示一次,因为前端在发送请求前应当进行了验证,而后端在验证不通过时直接报错即可,不需要任何提示。
第二,大部分业务错误发生时「客户端(不包括用户)没有任何处理办法」,这时候决定续延的不是机器而是人,码自然不如文字提示,简单地将错误消息发到 UI 上去即可。
以上两种情况,应当覆盖 90% 的业务场景,以及 99.9(99)% 的实际 HTTP 请求。
不能满足的有二:一、你在开发一个放给外部开发者使用的 API ;二、你在造一个奇美拉。
no1xsyzy
2020-05-29 19:23:27 +08:00
@no1xsyzy #108
说明一下,奇美拉的意思是缝合怪,也包括了所有微服务架构。
重点在于,奇美拉系统的重点在于各个部分是 “有机” 地结合的,任何一比特的信息(将来)都可能是有用的,那自然要从开头就写得容易被提取。不过建议用字符串当符号使,比数字好千倍。
{"result": 200, "data": ...} 和 {"result": "OK", "data": ...} 你想看哪个?

我觉得足以终结一切此类主题了。
xingheng
2020-05-29 19:27:06 +08:00
status code 和 response code 对我而言我能接受的,但是我写客户端的时候,在客户端会把这两个 code 映射成一个 int code,所以想问一下后端开发,现在 100<= http status code <600,那你们业务层的 code 一般是定义在哪个区间?
Leigg
2020-05-29 19:27:38 +08:00
虚心一点,多学习
myCupOfTea
2020-05-29 19:50:25 +08:00
@cheng6563 按照 restful 有啥招镣铐的,jira 算复杂吗,aws 算复杂吗
这边附上一个 jira 的 rest api 文档
https://docs.atlassian.com/software/jira/docs/api/REST/8.8.1/#api/2/issue-createIssue
xiangwan
2020-05-29 19:56:40 +08:00
@no1xsyzy 同学在#47 的焦点貌似是想操练下刚学到的定律。 @fatedier @Vegetable

随便搜了阿里云的错误代码,@no1xsyzy

例 1:

错误代码 Http 状态码 Message 描述
I400HD 400 Invalid Header ${HeaderName} ${Reason} HTTP 请求头非法
I400MH 400 Header ${HeaderName} is Required 缺少 HTTP 请求头
I400BD 400 Invalid Body: ${Reason} HTTP 请求包体非法
I400PA 400 Invalid Request Path ${Reason} HTTP 请求路径非法
I405UM 405 Unsupported Method ${Reason} 不支持的 HTTP 请求方法

例 2:

20 OK HSF 调用成功
30 client timeout 调用端超时
31 server timeout 服务端超时
40 bad request 请求不合法
50 bad response 返回结果不合法
60 service not found 服务没有找到
70 service error 服务错误
no1xsyzy
2020-05-29 20:03:03 +08:00
@xiangwan #113 精准符合例外一✔
no1xsyzy
2020-05-29 20:14:37 +08:00
@xiangwan #113 啊,不过休谟剃刀也算是刚学到吧,如果之前的话我会说珍珠效应的。
ihipop
2020-05-29 20:23:15 +08:00
@littleylv http 422
xiangwan
2020-05-29 20:28:51 +08:00
@no1xsyzy
我没办法反驳你的 #113
本来想先反驳第二点,写完后发现,开头写的是“大部分。。。“
然后再去看你说的第一点,描述的也是“大部分”状况
而且你还列了两个例外。

你的观点大部分时候是对的,另外的时候是错误的。
cabing
2020-05-29 20:35:15 +08:00
状态码不够多。
szyp
2020-05-29 20:40:53 +08:00
@littleylv 我司的参数检验返回的都是 400
no1xsyzy
2020-05-29 20:51:55 +08:00
@xiangwan 我的上面几个 “大部分” 都带兜底例外情况,“大部分”+“例外” 合起来估计超过 5 个 9 吧,并且例外还指明得挺精确的。
这就是像是 “重启解决 90% 的问题,重装解决 99% 的问题,重买解决 99.99% 的问题,其他问题不存在解决的办法”。

不过两个例外要重构一下:第一个例外是你不能或者不希望被调试,比如这一系统的持续运行非常关键,或者 API 的实际使用方是外部单位;第二的例外是整个系统活动部件非常多,做到有机结合,高聚低耦,并且每个部分常常单独变动。这两个例外实际上具有一体两面性:第一例外中把所有外部单位集合起来视作系统的一部分,就变成了第二例外;反之亦然。

但同时,我也要指出,这两种例外,真的碰上的情况实在太低,加起来,按场景流程计不足 10%,按实际 HTTP 请求数计不足千分之一,两种例外兜不住的情况低于十万分之一。如果谁觉得自己是十万里挑一的天选之人也欢迎讲故事。

至于我已经明确指出了例外的情形、发生的条件、构成例外的原理,你要觉得这也能算车轱辘话那我没话说。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/676678

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX