我的个人的理解还是,这么做比较规范
但是同事的理解更多是优点好处是什么
比如用户登录错误之前的方式都是返回 http 状态码 200
{
"code":4001001001,
"message":"用户登录失败"
}
现在按照规范应该是,返回 http 状态码 401 ,然后 json 还是老样子
首先非常意外,这个话题确实挺有争论的,评论太多了,抱歉不能一一回复。
公司太多项目各种问题,都是由于没有一个统一的规范,导致每个人都按自己的理解去写代码。
现在有个新项目,所以想定制一个规范(命名规范、异常处理、RESTful等等),大家都按这个规范来,避免一些以前的老问题,写出那些不好维护的代码。
当然我个人还是偏向于区分不同的HTTP状态码,而不是200一把梭哈。
其实又能引出另外一个话题,为什么POST一把梭哈的问题 🤣
当然这个同事们已经有共识了,确实区分会好点
101
wu67 2022-04-13 14:58:39 +08:00
月经帖....
目前一种比较常见的方法, 是 http code 管 http 请求状态; json 里面的 code, 管该请求的业务状态, 两个别混作一谈. 就目前国内应用乱七八糟的业务场景而言, http 状态码的使用, 很难覆盖到大部分场景, 那还不如直接 http200 一把梭, 靠业务 code 区分, 其他非 http200, 前端全部当成出错处理 |
102
sjdhome 2022-04-13 15:01:40 +08:00
只用 200 然后自己定义状态码无非是把 HTTP 当成传输层协议来用了,然后自己发明一套应用层协议。如果真有自己定义的必要那就直接重新定义新的应用层协议好了,别用 HTTP 套娃了。
|
103
TimPeake 2022-04-13 15:09:42 +08:00
散了吧 引战贴🤣
|
104
Chad0000 2022-04-13 15:09:55 +08:00 via iPhone
@sjdhome
严格遵守必有所失。比如下单前检查是否能下,是不是应该使用 get ?那么多参数对象数组嵌套你非用 get 折腾?某些场景允许 404 ,你非给我返回错误码,一堆可以接受的 404 不会给运维带来麻烦? http 传输层错误和业务层错误分开,有那么不堪一击吗? |
105
iyaozhen 2022-04-13 15:17:04 +08:00
|
106
iyaozhen 2022-04-13 15:20:25 +08:00
@adoal 哦哦,那认同你的观点。「为了方便监控离校系统调用图书馆系统接口时的业务逻辑错误率而想把我千奇百怪的业务错误码从 JSON 里提出来放到 HTTP 状态码吧。」这种是不支持的
这种就是业务自己日志监控或者埋点上报了 |
107
xuanbg 2022-04-13 15:50:26 +08:00
@sjdhome HTTP 是 HyperText Transfer Protocol 的缩写,翻译过来就是超文本传输协议,本来就是传输协议,怎么就不能当传输协议用?
|
109
lshero 2022-04-13 15:56:47 +08:00
我觉得最好还是提前沟通一下
因为接口的改动涉及的上下游不只自己一人,也许客户端不想在异常捕获里处理业务逻辑。 也许运维团队就想监控一下 status code ,判断一下服务是否正常,压根不关心你的业务逻辑对不对 |
110
stroh 2022-04-13 15:58:19 +08:00
说个地狱笑话:老板没给超过 post 返回 200 多余的工资
----来自一位曾经月薪 30k 的同事 |
111
yedanten 2022-04-13 16:09:10 +08:00 via Android
业务层返回的状态码一律 200 ,这才符合规范好吧,不然因为授权失败返回 401 到底是业务层出的问题还是 nginx 之类的 web 服务器配置问题亦或者是路由网关层拦截?而且按规范,你业务层都处理玩业务逻辑了,就是说明请求的资源是存在并且有业务处理结果了,当然是 200 啊
|
112
Nich0la5 2022-04-13 16:19:42 +08:00
以前因为用 40x 导致 nginx 误以为宕机,后来就干脆全 200 了
|
113
fkdog 2022-04-13 16:23:01 +08:00 1
其实原因在与,以前的 http 是用来传输超文本一类的资源的。现在应用复杂化,http 职责下沉,用来当成数据的封包协议。
很多大公司甚至连 location 都不用了,把服务名当成参数丢进 request body 交由后端路由。 陈皓的文章我看过,我觉得他说的也有道理。但是想想陈皓他本身是一个优秀的开发者,与他共事的人肯定也是很优秀。因此他很难想象在一些小公司里,水平良莠不齐的开发的想法是有多奇葩。国内的开发人员普遍缺乏工匠素养,外加国内的氛围就是抢用户市场、赚快钱,因此稳定的架构、夯实的基础并没有太多的价值。 我觉得,人应该灵活一点。面对水平低的同时,你花时间去和他 argue & debate 没有意义,不如直接是是是,能忍则忍,不能忍直接润。 |
114
bobo2 2022-04-13 16:25:32 +08:00
都返回 200 ,错误日志不就不存在了??那出问题怎么查日志?
|
116
lmmlwen 2022-04-13 16:41:18 +08:00 3
我看这里面一堆理论家,说状态码这好那好,但有人用吗,估计很少,因为会造成诸多不便,基本都是理论式编程
|
117
byte10 2022-04-13 16:43:37 +08:00 1
@Biwood 哈哈 用 404 劫持页面,这个鸡贼😂
@adoal 可以的 666 ,收录你的回答,以后可以用这个理由。 @BeautifulSoap 同意。 @1000copy 挺好的,收录你这些理由。 @alswl 同意,收录,单纯把 http 当做传输协议也未尝不可,尤其是在 app 端是更好了。 @adoal 挺好的分析 @MrSheng 😂,可以的。 @salmon5 真实了。 @3dwelcome 可以的,案例不错。 @lisongeee 哈哈跨界了 @coala restful 规范确实很难执行 @seakingii 我不喜欢 restful ,都是太过于理想了。 总结一下:业务服务还是 200 一把梭好,没有啥原因,把 http 当成一个传输协议,因为有可能用 mqtt ,也可能用 ws 。听话不然就会很惨的,以后会很惨,前端后端都惨。跟那个 restful 一样,最后四不像。还是把事情简单化吧,不然以后不会幸福的。 |
118
casxter 2022-04-13 16:43:50 +08:00
其实这是个公司历史遗留问题,公司用啥就用啥
|
120
skiy 2022-04-13 16:51:22 +08:00
因为状态码不够用?毕竟只取状态码无法判断是什么错误。
|
121
Chad0000 2022-04-13 16:55:25 +08:00
@bobo2
错误日志 Debug 日志,都有日志层统一处理,各开发语言都有这样的框架。你不能指望错误日志去 Nginx 的 Log 看吧? |
122
dwlovelife 2022-04-13 17:06:21 +08:00
很多人把状态码和业务码混淆来说了,首先 HTTP 状态码理所应当交给服务器去判断,这次请求到底是 200 还是 400 还是 500 ,难道你要在代码里因为业务问题,恰巧这个业务问题像是 400 请求参数错误,所以我给客户端返回个 400 ,看!你因为主观的判断修改了 HTTP 状态码,此刻它已经不纯粹了它到底代表 HTTP 请求的状态还是你业务的一种场景已经区分不了啊,所以业务码它就是业务码,HTTP 状态码就应该让服务器本身去决策
|
123
dwlovelife 2022-04-13 17:12:04 +08:00
再返回楼主的例子,它是一个登录错误,OK, 登录错误有很多种服务未授权 [类似于在黑名单] 、token 失效、秘钥不匹配,此时难道都要以 401 去返回给客户端么,那么这个 401 到底代表什么?倒不如定义一种业务码未授权比如是 1001 ,token 失效是 1002 、秘钥不匹配 1003, HTTP 状态码依然是 200, 为什么是 200 因为本次的请求是成功的它是服务表述的状态,而登录的未授权需要根据场景返回对应的业务码。个人理解
|
124
darknoll 2022-04-13 17:18:39 +08:00
问就是 post 200 一把梭
|
125
PEAL 2022-04-13 17:36:47 +08:00
都可以,全局统一就行了
|
126
est 2022-04-13 17:38:29 +08:00
RESTful 一时爽,nginx log 统计拆路径、状态码火葬场
|
127
xfriday 2022-04-13 17:54:47 +08:00
我说两点,
1. 把 code 放 body 里,除非 body 又是一个自定义的超文本协议,像 json 这种文本“协议”(包含通用 code ,data 可以理解为一种协议了)没法包非文本数据(你 base64 编码下当我没说) 2. 如果需要根据 code 动态序列化 data ,那反序列化要 2 次完成 |
128
xfriday 2022-04-13 17:56:32 +08:00
而 http 本身就是超文本协议,body 可以是文本,也可以是图片等二进制数据,status code 是在 header 里,而且是简单的基于行的协议,不需要反序列化就可以读取 status code ,根据条件解析 body
|
129
ryh 2022-04-13 18:22:03 +08:00
除了 4** 其他的真的是不适合用,而且不包括 404
你 404 了,谁知道是 API 端口没了还是没 query 到 |
130
rv54ntjwfm3ug8 2022-04-13 18:56:31 +08:00
测了下各大公司情况 v2ex.com/t/846785
|
131
zlo309618100 2022-04-13 19:23:22 +08:00
基于 httpcode 来实现的状态管理,我们的扩展性如何?
比如 502 ,就是服务器挂了呀,然后再在这上面加个业务含义。 怎么玩呢? |
132
ecnelises 2022-04-13 19:43:46 +08:00
联想到了吗,对 HTTP 是否应该使用状态码来表达业务状态的争议,其实颇像「使用异常还是错误码」这个同样老生常谈的问题。有些人大小事都要抛异常;另一些人尝试 catch 一切异常,并永远使用错误码。而当代码要接入一个现有模块时,事情变得更复杂了。
HTTP 通用的错误码( 4xx, 5xx )很有限,就像系统定义的异常类型,必然无法涵盖所有错误的情况。但我们不必做二极管,始终在上面提到的两种人间反复横跳:尽管很多错误码是和 HTTP 协议强相关的(比如 411 ),至少常用的 401/403/404 语义可以完美对应项目中一定会出现的几种错误情况;除此之外,简单用 400 表达请求有问题,500 表达服务端有问题,搭配自定义的错误代码即可。 另一个和是否使用 HTTP 错误状态码相似的争议,是「是否要以 REST 方式组织 API 」。是的,生搬硬套的 CRUD 语义没办法定义现实中的所有复杂情况,但也不该因此就彻底抛弃这套被广泛接受的代码组织思路:GET 不应有副作用,PUT 相比 POST 有幂等性;实在不行把一些操作都抽象成某个 Action ,然后所有有副作用的操作一律 POST 也比一团乱麻来得整洁。 |
133
l4ever 2022-04-13 19:49:53 +08:00 1
没什么好说的, 全是 200, 返回的数据必包含 code, 根据 code 判断.
好处是错误码可以自定义 n 多个. Http 状态码才几个. {"code":-1001, "msg":"登录失败, 用户名或密码错误"} {"code":0, "msg":"ok","data":{"user":{"name":"test"}}} |
134
afewok 2022-04-13 20:33:11 +08:00
盲猜,肯定有添狗说,国内不懂规范,国外严格遵守。并举例说,不遵守引发的问题。。
|
135
ipuhua 2022-04-13 21:34:10 +08:00 via iPhone
先用 http 状态码,业务上能行就继续。不能行自然就转了 200 一把梭了。我司是后者。
最大的转折点在于 httpcode 的数量太少无法应对复杂的业务状态。 |
136
kaiki 2022-04-13 21:37:30 +08:00
说个很简单的,一个是别人已经制定好的规则,一个是自己制定的规则,使用一个就行,两个都用不行。
前端后端都是自己做的话,哪个方便就哪个。 |
137
Soin 2022-04-13 21:44:41 +08:00
http 状态码数量太少,只能用于对出错情况进行分类
具体的错误还是需要使用业务状态码再次拆分 并且,http 状态码每种只用一个( 2xx ,4xx ,5xx )自定义的跟服务器返回的不冲突,这样也可以区分到底是服务器出问题还是业务出问题,至少可以解决接入监控的问题 |
138
cedoo22 2022-04-13 21:58:47 +08:00
面试面了几个,有外包经验的基本都是 200 一把梭。。。。简单来说就是图省事。
但凡规范化一点的,都是要区分几种基本的状态码。 200 ,400 ,401 ,403 ,500 等, 具体细化各有差别。还有说 http 状态只是给浏览器看的, 简直 2 |
139
liuidetmks 2022-04-13 22:10:29 +08:00 via iPhone
@afewok 恭喜你,猜对了,可惜没有奖励
|
140
Bromine0x23 2022-04-13 22:20:27 +08:00
个人倾向成功使用 2xx ;失败用 4xx 、5xx ,以 application/problem+json 格式表示异常信息
|
141
Vitta 2022-04-13 22:20:56 +08:00
一把梭的你们是不是很多都是 java 开发
|
142
yaott2020 2022-04-13 22:28:51 +08:00
我自己写代码的话,除了常用的错误就会用,比如 401 500 503 403 404 。如果是应用层级的错误一律 200 OK ,然后再在返回包里面标注错误码,错误信息。
|
143
bobo2 2022-04-13 22:50:22 +08:00
@Chad0000 正常来说,不都是 err.log 存放错误日志,out.log 存放接口输出日志么,都返回 200 ,不就都存 out.log 了,日志层再怎么实现也是要判断输出日志和错误日志的吧
|
146
adoal 2022-04-13 22:56:03 +08:00
如果发生错误,是与业务逻辑无关的系统错误(不论是客户端还是服务器,自己方还是外方),还是与系统无关的业务错误?前者表明系统没毛病,是用户操作的错,要由用户解决,并且允许出现的常态;后者表明用户操作没毛病,是系统的错,由技术人员(某方的开发或运维)来解决,即使发生的频率不低也不应该视为允许出现的常态。有些错误很容易分辨出属于哪一类,而有些就需要技术和业务都精通的老司机才能准确分辨。HTTP 状态码和 body 数据之争的本质是,针对这两类错误如何设计报错机制。
|
147
aragakiyuii 2022-04-13 22:57:36 +08:00 via iPhone
infra 都没有的就随便一把梭了,毕竟能用就行
|
148
txydhr 2022-04-13 23:10:24 +08:00
能 200 梭哈
意味着也可以 404 梭哈 反正都能打开网页 |
149
MrKrabs 2022-04-13 23:42:07 +08:00
http 状态码才几个啊,restful 也就是个野鸡标准罢了,又不是圣旨
|
150
a132811 2022-04-13 23:43:13 +08:00
就算是完全用 200 一把唆, 也得判断 http code 。
如果返回结果确实需要自定义 code ,就需要两层处理: // 第一层 无论如何都是要处理的 if(res.statusCode==200) { // 第二层再判断一下 code if(res.json().code==0){ // 正常业务代码 )else if(res.json().code==1){ raise Error(res.json().err) } }else if(res.statusCode==400){ raise Error(res.body) }else if(res.statusCode==401){ // 未登录..... }else if(res.statusCode==404){ // ..... }....500 ,501 xx -------------------------------------------------------------------------------- 如果返回结果简单,就用一层就够了。 (很多公司的 api 其实就一层: https://v2ex.com/t/846785 ) // 只有第一层 if(res.statusCode==200) { // 只要是 200 , 就是正确的结果,不需要加第二层 code 判断 // 正常业务代码 }else if(res.statusCode==400){ raise Error(res.body) }else if(res.statusCode==401){ // 未登录..... }else if(res.statusCode==404){ // ..... }....500 ,501 xx ------------------ |
151
jinliming2 2022-04-14 00:23:46 +08:00 4
HTTP 2xx: 正常结果,一定是成功的操作,仅包含业务数据,不包含其他内容 status: success 之类的
HTTP 4xx: 客户相关错误,状态码可以提供大范围的错误信息分类(未登录、无权限、访问频繁之类的),这些错误都是正常情况下的错误,可以给出具体理由的,属于预期错误,通常理论上完全不需要开发、运维介入的错误,用户自己知道错哪了,能不能解决也是用户自己可以判断的。 HTTP 5xx: 服务相关错误,可以通过状态码进行分类分为业务错误和网关错误。如果是业务自己的错误(比如数据库连接断了、空指针了之类的),那就是 500 ,这类错误通常是需要开发人员去定位的异常情况,也就是未知的 bug 。而网关错误通常是明确的,配置错误 502 、临时维护 503 、业务挂了 504 。 其中 4xx 和 5xx 错误,状态码只提供大分类,响应结构中再包含可公开的具体的细分错误详情。 举个例子:用户访问了一个不存在的 URL ,分为 3 种可能,1 业务错误:没有这个资源,2 业务错误:没有权限,同时需要防止用户了解资源的存在性,3 网关错误:找不到对应的业务。 对于 1 和 2 来说,返回 HTTP 404 再合适不过,HTTP body 指示找不到可访问的资源;而对于 3 来说,应该返回 502 ,HTTP body 指示找不到可用服务。 这样,在网关记日志的时候就不需要解析 HTTP body 了,通过状态码就能过滤出错误日志,并且按照大分类分好: 通常开发只需要关注 500 的业务错误、运维关注除了 500 以外的其他 5xx 错误。而 4xx 的错误通常只需要关注计数就行,错误数在一定量级以下就是正常,超过一定量级就需要报警让开发介入调查了。2xx 的日志只在查业务逻辑的时候才会关注,平时直接忽略。 |
153
Chad0000 2022-04-14 03:39:18 +08:00 via iPhone
|
154
mmmfj 2022-04-14 06:47:48 +08:00
有时候前端是允许一些异常情况的,但是你返回个 http 异常,太难区分了,不知道是真的服务器炸了还是特殊情况
|
155
summerLast 2022-04-14 09:30:53 +08:00
自己定义格式有什么好处吗?
|
156
nkidgm 2022-04-14 09:32:13 +08:00
以前还会争论一下,现在这两个其实都有存在的理由,对于公司项目跟着团队 leader 走就行了,对于自己的项目用哪个看自己习惯。
|
157
nyakoy 2022-04-14 09:36:47 +08:00
以前是 200+post 一把梭,现在在往 restful 走。毕竟有规范还是用规范吧
|
158
yc8332 2022-04-14 09:40:10 +08:00
感觉搞偏了。反正我们都是 code 是在返回数据里面。。http code 是代表请求的状态吧?我们从来不去改这个东西。
|
159
newmlp 2022-04-14 10:08:33 +08:00
当然 200 一把梭,业务层的错误为啥要用传输层的错误码表示?
|
160
sunny1688 2022-04-14 10:09:24 +08:00
我这边的做法是,200 状态码,业务数据一定有,而且前端那边不需要做任何判断,拿到数据直接处理即可,就拿 ajax 来说,非 2xx 状态码,走的是 error 回调,很多开源请求库也都是按照这种方式去处理,所以我这边是只用了 200+4xx ,5xx 就不用说了,一般也不会手动抛出 5xx 状态码吧!
|
162
e7 2022-04-14 10:30:09 +08:00
telnet 127.0.0.1 8080
Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. agsdfadf HTTP/1.1 400 Bad Request Connection: close Connection closed by foreign host. 协议是协议,业务是业务,日志、监控啥的是没 es 还是没 prometheus |
164
bfdh 2022-04-14 10:58:56 +08:00
200 一把梭,原因很简单,一些前端 /APP 端菜鸟根本不知道什么是 http 状态码。
|
165
night98 2022-04-14 11:05:16 +08:00
你是 leader ,直接推
不是 leader ,保持现状就行 菜鸡哪都有,打开各个大厂的页面你会发现各种奇奇怪怪的 http 用法,大厂里面也存在两级分化,这事没办法 |
166
l00t 2022-04-14 12:26:03 +08:00
监控不了是监控的问题,不要削足适履。
|
167
yamedie 2022-04-14 12:42:04 +08:00
路过围观一下,另外下次别刷前端娱乐圈了好吗?
|
168
wy315700 2022-04-14 12:57:13 +08:00 1
一般 HTTP 状态码用于通信状态
具体业务状态封装在 body 里 |
169
lff0305 2022-04-14 13:13:49 +08:00
不知道现在如何了, 十多年前某银行的防火墙 /F5 还是什么会自作主张的修改非 200 的 response, 变成类似
upstream: error 400 messge: ....... |
170
adoal 2022-04-14 13:17:26 +08:00
另外,HTTP API 给 web 前端浏览器里用 JS 调用和给第三方应用系统的后端调用也是两种不同的场景,对最佳实践的选择也有影响。
|
171
fromzero 2022-04-14 14:28:52 +08:00
http 层的 code 符合标准就行 。json 里面的 code 是业务相关的状态,随便怎么定义都行。
|
172
hejw19970413 2022-04-14 16:17:59 +08:00
两个字 就够了 规定!
|
173
AoEiuV020CN 2022-04-14 18:03:59 +08:00
不管有什么优点有什么理由,修改这个都是麻烦,没好处,
|
174
cozof 2022-04-14 18:44:20 +08:00 via iPhone
应用层永远不应该去修改 http code
|
175
hlayk 2022-04-15 09:59:02 +08:00
https://www.v2ex.com/t/808610#reply44
有一点楼上没提到过的 在 Android 这边若使用网络请求框架 retrofit (业内排第一的网络框架)对于非 200 的 http code 是直接抛异常的 所以若返回非 200 的 http code 我们需要 try 然后再去解析 这非常的不优雅 |
176
chanchan 2022-04-15 10:40:00 +08:00
有些人跳脱出技术讨论,直接就认定自己是对的,别人是错的,说什么别人就是懒、摆烂、什么"封闭文化"之类的。真让人恶心
|