API 不管操作成功还是失败都返回 200 状态码,自己在返回结果里又定义一个表示是否成功的属性是从哪里传开的坏习惯?

2022-12-03 21:22:25 +08:00
 edis0n0
一直以为是从阿里开始传到整个中国互联网企业的坏习惯,最近发现一些日本网站也都这样做。但欧美网站大部分不这样做,例如 stripe ( https://stripe.com/docs/api/errors) twitter 等,都是规范的使用 http 状态码表示操作成功或失败,但 google 一些没有公开文档的私有 api 返回状态也非常混乱
7515 次点击
所在节点    程序员
92 条回复
edis0n0
2022-12-03 22:21:43 +08:00
@dddd1919 #20 具体那个?我.NET 这边直接 return NotFound(); 给框架处理就行了,都不用自己实现
dorothyREN
2022-12-03 22:23:47 +08:00
有没有可能 200 表示请求成功,自定义的 code 表示操作失败了
thevita
2022-12-03 22:24:10 +08:00
没这么复杂,也没有谁正确一说,说到底取决于你要传递给调用者的 “语意”
如果你的 API 是标准的 rest ,即 对 “资源” 的 curd ,那么这个时候是能跟 rest 的语意完全匹配的(其实大部分时候都是这样的 api )

但事上总还是有一些再这之外的复杂一点的逻辑, 要么就 自己在业务模型上封装各种错误,要么就全局封装一个,我理解这是一种在 rest 之上的具有业务语意的扩展而已

---


@swulling
我感觉....,上一个应用我就把服务的错误和资源相关的放 http status ,把 某些业务错误 放 body 了,,这样应用可依据具体情况决定是否处理,怎么处理,当然本身也不一样,前端应用业务逻辑也很重的原因
bug123
2022-12-03 22:24:22 +08:00
如果返回 500 ,怎么确定是进程挂了,还是进程处理出错了?
edis0n0
2022-12-03 22:31:06 +08:00
@bug123 进程挂了 还是进程处理出错了 这种给运维人员看的东西不是应该写在日志里吗,你总不能把数据库连不上这种信息直接返回给用户吧,所有内部错误对用户来说都是一样的他们解决不了的
dzdh
2022-12-03 22:34:41 +08:00
- api token 错误

- IP 被拉黑了

- 超过了资源限制

- 试图访问不被授权的资源

按照 http status code 应该统一给 403 的 code (或者有几项应该用 401 和 429 ),但是实际业务中表述不够清晰。

调用方会忽略 http status code (比如我)直接用 response 来进行业务流程的判断。IP 被拉黑了我会判断 response ip rate limited 然后换个 ip 。但是这个表述可能会有变更,我的判断就不生效了,所以业务方会 statuscode:403, body.code:IP_RATE_LIMITED, body.message: ip rate limited 。

然后因为某种资源受限而本次访问不被许可可能会有更上一层的大的集合性表述,那可能是 body.code:FORBIDDEN, body.ErrorCode:IP_RATE_LIMITED, body.Message:ip rate limited. 当然可以用 status403 ,但是从 [调用方便] 我不用从 header+body 里分别取我觉得调用方就很好接受。


业务接口是给人用的,方便才是真理。PHP int+string 我管他啥类型,有结果就行。
edis0n0
2022-12-03 22:37:51 +08:00
api token 错误应该是 401 超过了资源限制应该是 429 吧
shakukansp
2022-12-03 22:41:20 +08:00
楼主讲一下 token 没过期鉴权失败,没 token ,token 过期
都是 40 几?
edis0n0
2022-12-03 22:41:59 +08:00
@shakukansp 403 400 403
deef
2022-12-03 22:42:57 +08:00
有没有想到问题出在很久以前的 http 时代的运营商头上,当年三大运营商可都是对着 HTTP403 、404 、503 、502 等状态给你返回一个“X 通智能纠错页面”(其实是放广告)你要是碰见这种 IDC ,你还敢用 HTTP 状态码吗?

所以 HTTP 200 没什么问题,表示网络没问题就好了。
shakukansp
2022-12-03 22:43:33 +08:00
@edis0n0 那鉴权失败但是不跳转登录,token 过期要跳回登录页你怎么区分?还不是要在返回结果里区分吗
Leviathann
2022-12-03 22:46:37 +08:00
@edis0n0 spring 的 rest template ,相当于一个 http client ,当时我第一次发现这玩意请求返回不是 200 居然用抛异常来表示的时候也是震惊的,什么 nt 设计
edis0n0
2022-12-03 22:54:46 +08:00
@shakukansp #31 发现很多层没理解我的意思,我的想法是少额外包装一层,直接用状态码是否 200 判断是否失败,成功的话整个返回都作为 data 处理,失败的话整个返回结果都作为 error detail 处理,这样更方便资源消耗更少
劫持问题现在基本都有 HTTPS 了吧
wu67
2022-12-03 22:55:17 +08:00
这个问题不是本站早就讨论过了几次吗? 网络请求状态码和业务状态码不要混作一谈, 一个是协议一个是应用业务, 二是业务量上来之后, http 状态码已经不足以表示这么多的业务异常状态了.

所以我也赞成 @swulling 说的 200 + 业务状态码 + 全 post + json/form data, 足够清晰, 并且能有效避免很多 cv boy 瞎复制代码, 例如要给 get 型接口的 body 里带 json 参数, 或者 post 型的参数要全部拼刀 query 上面...
wangritian
2022-12-03 23:15:20 +08:00
楼主把自己不认同但其实有相当合理性的方案偏激地归为坏习惯的这种坏习惯不太好
上面很多回复已经指出了网络状态码和业务状态码混用的缺陷了,而拆开用仅仅不符合你的喜好,或者,省几字节流量?
iseki
2022-12-03 23:20:48 +08:00
早期的时候状态码非 2xx 会被篡改,同时没有传输层安全,所以衍生出了这种怪用法。现在很多人改不了,有些前端、后端因为自身水平问题竟然会告诉你不是 200 的就没法统一封装······然后他们还觉得他们这种统一封装的方法挺好,所以就这样了呗(直到现在在某些特殊的场景还会存在 200 劫持行为···)
iseki
2022-12-03 23:23:11 +08:00
我也支持以 2XX 表示成功,以 4XX/5XX 表示失败,并在失败时内部包含业务用错误码的做法。这样的好处主要是不侵入响应体,可以兼容响应体是 JSON 以外内容的情况,同时也极大规避多态反序列化
copymaster
2022-12-03 23:27:52 +08:00
什么坏习惯啊,http 状态码 200 说明请求和相应是在系统业务内正常的,返回数据代的状态码是这个系统业务的代码
ychost
2022-12-03 23:30:05 +08:00
规范统一就好,我个人喜欢仅用 POST/GET ,不用 DELETE/PATCH/DELETE ,在 body 里面包装 code 和 message ,因为 header 的 statusCode 不好扩展,而且仅支持数字,很多时候 code 是个字符串
so1n
2022-12-03 23:33:31 +08:00
支持全 REST 的就是没有经历过运营商篡改和 CDN 的兼容情况

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

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

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

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

© 2021 V2EX