V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dunhanson
V2EX  ›  程序员

为什么要区分不同的 http 状态码?想说服同事

  •  3
     
  •   dunhanson · 2022-04-13 10:28:42 +08:00 · 17165 次点击
    这是一个创建于 955 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的个人的理解还是,这么做比较规范

    但是同事的理解更多是优点好处是什么

    比如用户登录错误之前的方式都是返回 http 状态码 200

    {
      "code":4001001001,
      "message":"用户登录失败"
    }
    

    现在按照规范应该是,返回 http 状态码 401 ,然后 json 还是老样子

    第 1 条附言  ·  2022-04-13 16:08:46 +08:00

    首先非常意外,这个话题确实挺有争论的,评论太多了,抱歉不能一一回复。

    公司太多项目各种问题,都是由于没有一个统一的规范,导致每个人都按自己的理解去写代码。

    现在有个新项目,所以想定制一个规范(命名规范、异常处理、RESTful等等),大家都按这个规范来,避免一些以前的老问题,写出那些不好维护的代码。

    当然我个人还是偏向于区分不同的HTTP状态码,而不是200一把梭哈。

    其实又能引出另外一个话题,为什么POST一把梭哈的问题 🤣

    当然这个同事们已经有共识了,确实区分会好点

    176 条回复    2022-04-15 10:40:00 +08:00
    1  2  
    cxe2v
        1
    cxe2v  
       2022-04-13 10:32:20 +08:00
    200 一把梭可以避免很多麻烦
    NCry
        2
    NCry  
       2022-04-13 10:35:17 +08:00
    http 状态码目前在我这边使用过程中就是拿来给浏览器看的,实际业务中并不会用到。
    zmal
        3
    zmal  
       2022-04-13 10:37:02 +08:00   ❤️ 2
    wolfie
        4
    wolfie  
       2022-04-13 10:37:36 +08:00   ❤️ 84
    ZE3kr
        5
    ZE3kr  
       2022-04-13 10:39:33 +08:00 via iPhone   ❤️ 1
    还有一个好处,就是 Nginx/Apache 不用解析 json ,可以仅根据状态码记录 Log (比如仅 5xx 的记录 log ,其他的不记录。如果因为种种原因愿意通过 Nginx 记录日志而不是其他地方的话)
    Chad0000
        6
    Chad0000  
       2022-04-13 10:41:58 +08:00   ❤️ 1
    我是一律 200+Post ,虽然有点不规范但省了很多事情
    gam2046
        7
    gam2046  
       2022-04-13 10:44:25 +08:00
    没什么优点。特别是 API 请求,有效的状态码可以让浏览器为用户显示友好的错误提示,但 API 请求,几乎不存在用户直接请求的情况。

    REST 那一套说是可以更有语义化,但由于实际业务的复杂性,依靠 HTTP CODE 很难表达出含义,最终还需要在响应体内自定义错误码,这就是重复工作了。

    统一返回 200 以及统一 POST 一把梭,确实不够优雅,但是能用,而且也没什么副作用。
    yuxing1171
        8
    yuxing1171  
       2022-04-13 10:44:39 +08:00   ❤️ 32
    也就见国内公司的经常用这种 200 走遍天下,无视 HTTP 状态码,国外的 API 很少见这样做的。这种格式给调试造成非常大的困扰,看着就恶心,已经到了走火入魔的地步,严重阻碍技术的进步。公司刚招了个毕业没多久的,问 HTTP 状态,基本啥也不知道,一问是原来的公司都是这种做法,自己 body 里面定义状态码,从来不关系 HTTP 自己状态码,真被害的够惨的。 这种格式早期是为了应对国内恶心的运营商拦截消息而不得已的做法,但是现在因为普遍使用 HTTPS ,已经没有了这种情况,还继续使用真没必要。
    andyskaura
        9
    andyskaura  
       2022-04-13 10:45:05 +08:00
    现在的做法是 只要是业务返回 统统 200 即便有问题
    monkeyWie
        10
    monkeyWie  
       2022-04-13 10:46:45 +08:00
    业务层一律 200 ,非 200 的应该是网关层的事,对接飞书 Open API 的时候也是这样设计的,如果是业务异常都是 200 ,但是触发限流之类的网关层异常,就是非 200 了
    yuxing1171
        11
    yuxing1171  
       2022-04-13 10:47:42 +08:00   ❤️ 8
    200 走遍天下,对于调试和监控都非常不友好。调试的时候不得不解析 body 才能知道是否真的成功。而监控更加困难,通常监控不会去解析 body 数据,都是 200 那你让监控怎么判断是否成功?
    hope4tomorrow
        12
    hope4tomorrow  
       2022-04-13 10:48:15 +08:00
    做监控的话,用标准可以省很多事,例如,在 prometheus 中查询非 200 响应的记录,就很自然
    cpstar
        13
    cpstar  
       2022-04-13 10:48:27 +08:00
    一个写在 ajax.error()里,但这就不能区分协议基础问题和业务故障问题
    一个写在 ajax.ok()里,然后 if errcode ,这就区分了协议基础问题和业务运行问题
    JamesMackerel
        14
    JamesMackerel  
       2022-04-13 10:50:26 +08:00 via iPhone
    @cxe2v 一个典型的例子就是,调用方如果是 Java 服务用的 RestTemplate 的话,那么除了 2xx 之外会抛异常,需要额外的配置才能不抛异常……
    masterclock
        15
    masterclock  
       2022-04-13 10:51:45 +08:00
    如果已经有规范,比如 RESTful ,那就按照规范来
    如果还没有规范,那就起草个规范,然后按照规范来
    但说实话,这好好的,干嘛要自己去发明个轮子
    angryfish
        16
    angryfish  
       2022-04-13 10:52:04 +08:00
    首先问一个问题,返回 401 装态,和返回 200 状态,前端的工作量有变化吗?后端的工作量又变化吗?
    作为使用 spring boot 的,我觉得返回 401 ,后端的工作量是增加了的。不知道前端是否会增加。
    Leonard
        17
    Leonard  
       2022-04-13 10:54:06 +08:00
    整个项目统一,别随时改一会是这一会是那就行
    Jooooooooo
        18
    Jooooooooo  
       2022-04-13 10:55:05 +08:00   ❤️ 1
    用 http code 的问题在于, 很多时候, 得判断两次.

    异常状态随便举例子 下游调用超时, 内部异常(比如空指针), 下游异常数据, 用户没登录, 用户状态不正确, 用户行为不正确, 可能是爬虫(返回打乱的数据), 可能是爬虫(不返回数据)

    我们是用自定义 code:0 表示正常, 其他值表明是各类异常.
    Lin0936
        19
    Lin0936  
       2022-04-13 10:57:08 +08:00
    最恐怖的是现在项目 API 有的返回 200+错误 json ,有的返回 401 。。。
    dunhanson
        20
    dunhanson  
    OP
       2022-04-13 11:00:30 +08:00
    😂 看来争论挺大的
    AyaseEri
        21
    AyaseEri  
       2022-04-13 11:02:29 +08:00
    5xx 不好判断是自己应用的问题还是 pass 层的问题,我们一般通过 4xx 能判断出 nginx 是否配置正确,503 的话就说不清了,可能 pass 层挂了,可能容器挂了,也可能手残把地址输错了。
    我的意见就是,如果这个规范可能导致你们加班时长变多,那就不要实施。
    Davic1
        22
    Davic1  
       2022-04-13 11:02:37 +08:00
    屎山的来源之一就是 200 一把梭?
    dunhanson
        23
    dunhanson  
    OP
       2022-04-13 11:03:47 +08:00
    @wolfie 很形象 哈哈
    daimiaopeng
        24
    daimiaopeng  
       2022-04-13 11:04:57 +08:00
    @wolfie 图不错
    alswl
        25
    alswl  
       2022-04-13 11:07:59 +08:00
    统一返回 200 以及统一 POST 一把梭,如果明确了错误返回结构,统一了各个基础设施的认知,建设了响应的工具。没问题,你甚至可以剥离掉 HTTP ,剥离掉 Cookies ,什么都不用。就是把 HTTP 当作传输层。

    如果上面三者做不到,干嘛不遵循标准的 HTTP Schema 协议?
    jorneyr
        26
    jorneyr  
       2022-04-13 11:08:37 +08:00   ❤️ 10
    尽量不要把 HTTP 状态码和业务码混用。
    BeautifulSoap
        27
    BeautifulSoap  
       2022-04-13 11:12:07 +08:00   ❤️ 5
    对接过一些接口的表示,返不返回错误状态码对写代码的人来说没什么区别

    200 一把梭也是有它自己的好处,最典型的就是调用对方 api 的时候,只要不是 200 那你就知道这次 api 调用 100%是出了幺蛾子了,而且错误不在对方服务器上面

    而区分不同状态码的话,你是没法单纯通过状态码来判断这个 api 请求到底是 API 本身出错了,还是对方服务器前面的 Gateway 或者 Load Balancer 因为什么原因出错了返回了非预期的 http 状态码。从写代码角度,反正到头来我还是得取出返回值具体分析到底是服务出错了还是其他的网络错误,比 200 一把梭麻烦多了
    kaedeair
        28
    kaedeair  
       2022-04-13 11:12:53 +08:00
    当使用这个接口需要授权,但是传输的数据的不是这个授权主体时,比如:
    机器 A 使用 token 认证,当不同用户在机器 A 登陆时,401 就会有问题,会分不清是机器的 token 过期还是用户名密码错误
    我这边都是用 json 的 code 表示对数据的处理结果,外层的 httpcode 表示数据的传输情况
    twing37
        29
    twing37  
       2022-04-13 11:13:03 +08:00
    是不是搞混了一个概念:

    制定标准的意义就是为了更清晰不是么.

    如果 x 公司的标准非外部,爱咋弄咋弄~ 黑话也是话.

    但如果跨出门了.有个更标准的规则遵循.即说普通伐更省事
    icyalala
        30
    icyalala  
       2022-04-13 11:16:01 +08:00
    单纯对于你的例子,如果后面需要区分错误类型:用户不存在、用户密码错误、用户被封禁,用什么状态码呢?
    micean
        31
    micean  
       2022-04-13 11:18:17 +08:00
    很多时候状态码不一定是业务给的,比如防火墙,会带来困扰
    andiest
        32
    andiest  
       2022-04-13 11:18:30 +08:00
    本人遇到过开发同事乱用 http 状态码,导致 cdn 商的负载均衡算法以为源站点服务器有问题,一直切换源站点。
    weixiangzhe
        33
    weixiangzhe  
       2022-04-13 11:18:59 +08:00
    月经贴啊,每月都有这种贴子
    1000copy
        34
    1000copy  
       2022-04-13 11:19:29 +08:00
    应用软件和 HTTP 的关系,就像你和电信局的关系。

    你如果以自己为中心,就把电信局当成一通道,至于电话局定义的 200 ,400 这些代码,你管他呢,你只管摘机+说话+关机。至于摘机代码是啥,你管他的。你把我要传递的传递过程,如何解释,是我的事情。

    你以电话局为中心,那么你就真的要考虑如何诊断,如何监控,各种屁事。

    所以你是写 HTTP 插件的,还是你写软件,而 HTTP 只是你的传输通道?

    学到了 HTTP 各种协议,就忘掉了软件需要封装,分层了吗。

    为什么软件内需要知道通道的细节呢。知道了细节,软件就会被拴在通道上了。

    今天 HTTP 定义了 200 ,300 ,400 ,500 ,明天换成别的协议,是 OK ,Failure ,你的软件就改了底朝上了啊。
    guyeu
        35
    guyeu  
       2022-04-13 11:21:38 +08:00
    想问下楼上鼓吹 restful 风格的大佬,业务内部的错误码咋给客户端? 401 Bad Request + {"err": 1001, "msg": "are you ok?"}
    chendy
        36
    chendy  
       2022-04-13 11:22:42 +08:00
    全 200 更合适
    市面上的开发,知道 http status 是啥的其实都不多
    直接无视这个概念,全部塞进 body 里返回可以避免很多不必要的沟通和解释
    另外如果需要做分析统计之类的,错误代码往 header 里塞一份就行了

    另外不是国外没人用全 200 ,只是常见的大公司接口做了状态码区分,小厂的,传统软件厂的接口也有全 200 的
    MrSheng
        37
    MrSheng  
       2022-04-13 11:27:51 +08:00
    Nginx 自定义了 499 状态码,请问为何不使用已有的状态码呢?
    adoal
        38
    adoal  
       2022-04-13 11:29:15 +08:00   ❤️ 27
    用 HTTP 状态码表示业务结果,需要对业务和技术都有深刻理解的老司机做精心设计,否则会画虎类犬。
    HTTP 状态码数量就那么一些,而业务的结果状态数量是不可控的,随着业务接口膨胀起来,如何映射到 HTTP 状态码的分类,如何表示业务状态细节,都不是空口说一句优雅、规范就能解决的,是要实打实一个个干出来的,要踩坑踩水甚至踩屎的。
    在实际架构中,可能经过 API 网关以及其它各种反代和中间件,业务状态逐级向上传递,业务状态码跟基础设施状态码在同一个命名空间,必然会导致设计工作量和难度更大。
    最后,在 HTTP 状态码的命名空间里表示业务状态,受惠最大的其实是做系统运行状态监控的。但,同样的问题,如果没有业务和技术都足够资深的老司机来做设计,很可能出现监控信息的无序,失去意义,甚至搞出用 AI 过滤有效监控异常的笑话。
    先不说团队素质、集成方团队素质、遗留系统对接之类的非技术问题吧。
    总之,理想很美好,但是,陈皓给用户方做咨询的顾问团队能做好的事,不等于人人都能做好。
    lisongeee
        39
    lisongeee  
       2022-04-13 11:31:42 +08:00
    我的评价是用 json-rpc 更好一点,拒绝扯皮
    salmon5
        40
    salmon5  
       2022-04-13 11:32:53 +08:00   ❤️ 1
    全 200 更合适
    国外那套根本就是 hello world 级别的,没什么卵价值
    0x49
        41
    0x49  
       2022-04-13 11:33:07 +08:00   ❤️ 2
    http status 仅用来判断系统是否有异常,业务的状态放 body 里
    wherewhale
        42
    wherewhale  
       2022-04-13 11:36:22 +08:00
    国内那会 care 这些 实用主义至上的氛围 远离这种业务团队吧
    MrSheng
        43
    MrSheng  
       2022-04-13 11:41:36 +08:00   ❤️ 5
    用 HttpCode 的能不秀优越么,甚至说出了阻碍技术进步的话,不觉得搞笑么?
    来贴段代码让大家看看
    talk is cheap,show me the code
    echo1937
        44
    echo1937  
       2022-04-13 11:49:12 +08:00 via iPhone
    国内普遍 200+post 一把梭
    makelove
        45
    makelove  
       2022-04-13 11:52:45 +08:00
    用 http code 分类一下有这么难吗?
    哪怕是在浏览器里,搞成一堆 200 成功请求难道要一个个打开内容去检查是不是有错误回应?
    daimubai
        46
    daimubai  
       2022-04-13 11:54:30 +08:00   ❤️ 40
    我的做法是:
    全 200 也不合适吧,通用的状态码应该保留

    200 统一表示成功。
    400 统一表示客户端参数错误、业务错误
    401 没登录
    403 没权限
    404 接口不存在(一般 web 框架会处理。 如果请求的资源不存在不返回 404 的,比如用户不存在,就返回 400)
    500 统一表示服务器异常

    对于 200 ,响应体要不要包一层,可以再开一个贴子开撕,我的话是包的:{code:"0", message:"success",data:{}}

    如果 400 或者 500 的话,返回{code: "-1" , message: ""},-1 表示通用的业务异常,前端只需要取 message 弹窗即可。如果前端需要对业务异常进行逻辑判断,然后再自定义 code ,前端根据 code 去判断。


    如果你的项目要做 saas ,给其他公司接,你也全 200 ?
    remember5
        47
    remember5  
       2022-04-13 12:00:18 +08:00
    @daimubai #46 想法一致
    hopingtop
        48
    hopingtop  
       2022-04-13 12:07:03 +08:00
    @daimubai 与你完全一致
    Freeego
        49
    Freeego  
       2022-04-13 12:07:23 +08:00
    讲道理 http 状态码不是应用层的问题。全部用 http 状态码一个难以保证所有接口的返回结果都能找到对应的码,第二个难以区分是业务的问题还是更上层的传输的问题。我目前的做法是,对非 200 的返回直接显示系统异常,200 的再取里面的自定义状态码区分具体业务结果,只要有清晰的文档,这样完全没问题。
    WispZhan
        50
    WispZhan  
       2022-04-13 12:14:16 +08:00   ❤️ 3
    我就想问,说 200 一把梭的。是不做监控还是啥?

    只能说野路子真多
    echo1937
        51
    echo1937  
       2022-04-13 12:15:30 +08:00   ❤️ 1
    不要把 HTTP 状态码和业务码混为一谈,状态码不是用来代替业务码的,而是把内部信息暴露给外部的。
    Huelse
        52
    Huelse  
       2022-04-13 12:21:46 +08:00
    http 状态码就是 http 状态,业务就是业务,不搞什么“大一统”,顶多就是第一位关联
    adoal
        53
    adoal  
       2022-04-13 12:21:47 +08:00
    @adoal 我这么说倒不是反对用 HTTP 状态码表示业务状态,而是说要想清楚以自己的团队和周边状态、项目背景、后续配套支持力度,甚至是组织机构设置、职权划分、撕逼流程,这样做是否真的能把事情做得更好,需要付出什么样的代价,做得更好的结果是否会引发其它可能的问题?工程上做选择都是 trade off ,有些看起来好的,能不能落地好是要结合实际的。
    yangyaofei
        54
    yangyaofei  
       2022-04-13 12:25:33 +08:00
    "我们不吃(不用)那一套(已经定义好的状态), 要摸着石头过河(自己再定义一套一样的)", "都是国外用的玩具项目采用的", "又被卡脖子了, 真是亡我之心不死", "gayhub 不能上了"

    矛盾不矛盾
    ClericPy
        55
    ClericPy  
       2022-04-13 12:33:40 +08:00
    如果平时不分析 nginx 日志, 不操心普罗米修斯做各种指标分析, 小公司爱咋咋的吧, 大厂的话, 技术评审感觉都过不去, 没必要和这些人争论.

    不论对错, 只论适合不适合, 有些挣快钱的公司真的就是能用就行. 而且多数情况不怕做错, 怕的是不统一, 一错到底比有对有错带来的危害要小一点

    你要做的大概不是来 V2EX 找认同, 而是提升自己然后尽早摆脱这种环境
    yangyaofei
        56
    yangyaofei  
       2022-04-13 12:34:26 +08:00
    其实, 你看不看已经没用了, 两方的出发点(理论的基础)都是对方否定的. 所以再说也没用.

    反正. "能用就行" 这种我是不敢用的, 必然会在能写屎山的地方写屎山, 简单的复合协议都不愿意做, 我不认为会写出好维护的代码.

    手艺人都有手艺人自己的优雅和细致, 手艺人和大锤 50, 不一样.
    Biwood
        57
    Biwood  
       2022-04-13 12:37:23 +08:00   ❤️ 2
    我认为这才是真正的“卷”。

    最开始是运营商或搜索引擎根据 404 劫持页面,然后是网站服务方不得不全站 200 ,在然后形成了习惯、偷懒,美其名曰灵活、自定义规则,明明有 https 了却还是 200 一把梭。封闭文化始终存在与这个国家的方方面面,这根现在简体中文互联网整体的割裂基调是一致的。

    V2EX 虽然有不少程序员,但是这个问题如果放到真正的技术网站,甚至根本都不应该成为一个问题。
    adoal
        58
    adoal  
       2022-04-13 12:37:45 +08:00   ❤️ 21
    至于拿监控说事的……监控啥?

    如果是为了监控基础设施,我 JSON 里封的是业务逻辑层面的错误,关你基础设施屁事?

    如果是为了监控业务错误,却嫌错误代码封在 JSON 里不方便……你就是想让我把业务错误代码放到 HTTP 里去对吧?你是不是觉得我这边各种各样的业务错误怎么映射到 HTTP 那几个状态码里很简单?你个普罗米修斯崽懂个屁的业务。

    我的业务 API 又不只是为了让你来做监控而存在的,我要给别的业务单位调用啊。HTTP 状态码没出错,业务状态码出错的时候,可以去找管业务系统的人处理,HTTP 状态码出错了找管基础设施的人处理,这两拨人不是同样技能的啊。业务端有个什么狗屁错(而且还不是那种 unrecoverable 的外部环境错,是业务逻辑的错,要业务用户处理的)都返回成 HTTP 错误码一级一级传上去,查个业务级错误都要基础设施的人联动,这是制造民怨吗?你来给我做基础设施架构让我有办法一键定位出错的层次和节点吗?可是我只能拿到够做业务功能的经费,而且是单个单个项目做,没有做基础设施的条件,我让一个行业人士起家的地方性行业性中小型业务信息化开发商给我做业务系统开发的时候顺便免费做一套云原生的微服务的可观测的可这个那个狗屁的基础设施,并且以后的其它同类业务开发商要逼着他们不允许用自己的积累,一定要做在这些所谓现代的平台上,这忒外祖母的现实吗?
    libook
        59
    libook  
       2022-04-13 12:41:23 +08:00   ❤️ 6
    401 指的是 Unauthorized ,是接口要求必须登录过才可以调用,不是登录失败。

    HTTP 是有标准规范的,所有状态码都有定义。https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

    需要注意的是:
    1. 标准里对状态码的定义仅与 HTTP 协议通信的状态有关,跟业务无关,比如 401 仅代表 HTTP 协议层未认证,不代表业务上未认证,虽然有时候两者是同一件事。
    2. 通用的 HTTP 客户端和服务器软件及其相关的框架和库都是会默认遵照 HTTP 标准规范来设计的,你可以不按标准使用,但你使用的软件、框架和库可能依然会按照标准来反应。
    3. 有的 API 设计风格(如 REST )会把业务状态和 HTTP 状态绑定一起,但这是建立在业务状态足够简单的基础上的,HTTP 状态码就那么多,无法把所有业务状态全映射到,比如登录失败可能有多种原因,客户端需要对不同原因进行判断再做反应,此时仅一个 400 状态码是没法解释清楚的。

    建议先对 API 进行梳理,然后划分出哪些接口要用什么设计风格;对于可以遵照 HTTP 标准来设计的接口,需要去分别考虑每种返回情况的 HTTP 状态是什么、业务状态是什么,给出正确的 HTTP 状态,并在载荷中写明业务状态。
    adoal
        60
    adoal  
       2022-04-13 12:41:54 +08:00
    当然,我坚决反对 JDBC 连不上数据库服务器的时候抓出来异常还要包到 200 里向上返回……业务逻辑上的错误(责任在甲乙方最终用户,不涉及基础设施运维)用 200 包起来返回是一个美丑的问题,基础设施错误还要这么搞,是沙雕还是沙壁的问题。
    binux
        61
    binux  
       2022-04-13 12:45:37 +08:00 via Android   ❤️ 10
    工作量增大?需要而外配置?区分错误类型怎么办?你看看国内的开发者们都在考虑些什么!

    你知道国内 200 一把抓的风气恶心之处在哪吗?
    不在于这么做理由,或者说觉得不区分有多好,而是他们根本就不去想理由,麻烦就不去做,别人发布了规范也不去看,闭门造车而洋洋得意。

    我很同意 coolshell 里的一个观点,rest API 规范不一定普世,但是人家好歹有成文的规范,也会写这样选择的原因,你可以自由讨论,指出它的问题。你觉得 200 一把抓好,那你见过有那个大厂有成文的规范 guidance 吗?

    整天在那讨论政治,说没有参与权,到了真正程序员能有话语权的标准的时候又在那里摆烂,简直就是叶公好龙。
    infun
        62
    infun  
       2022-04-13 12:46:35 +08:00   ❤️ 1
    支持 200+post 一把梭
    yzbythesea
        63
    yzbythesea  
       2022-04-13 12:48:36 +08:00
    200 走天下,可是我 grpc 的设计师吗?(狗头

    已经被 grpc 的 200 OK 接一个 INTERNAL ,UNAVAILABLE 整怕了。
    Biwood
        64
    Biwood  
       2022-04-13 12:53:56 +08:00
    V2EX 不适合严肃的讨论技术,散了吧。我建议去 stackoverflow.com 或者别的什么专业点的技术社区提问。这里是“创意工作者们的社区”,不是技术问答社区。
    CEBBCAT
        65
    CEBBCAT  
       2022-04-13 13:13:17 +08:00
    我现在认为 HTTP 状态码是一个副信道,在 payload 之外提供了醒目的消息。比如抓包排障,一屏幕的 200 和 200/4XX ,显然区分了状态码的报文更好阅读
    coala
        66
    coala  
       2022-04-13 13:14:09 +08:00
    尝试过 RESTFull, 但是没有完全遵守起来, 现在个人的实践,
    http code 500 服务器真的内部错误.
    http code 401 未授权
    http code 200 (业务 code 400 是密码错误这种), 就是业务上的错误,我认为是成功的, 让让前端会有个统一的拦截器去处理业务 code

    原则就是 http code 必须保证符合原有的意思, 200 里面再加上业务 code,
    但是像是未授权这种, 可能既是业务错误, 也可以理解为 http code 错误 就很头疼

    RESTFull 我遇到的问题(Java):
    1. 有些内网的防火墙不允许 delete 这种请求进去.. 很让人无语
    2. RESTFull 一个 URL 可能对应多个接口, 按照路径配置各种规则的时候 , 日志打印, 就打地址的话看不出调用是那个具体接口, 解决其实也能解决, 日志加上请求的方式, 规则按请求方式 + URL 去配置.
    3. 就是理解不明确的, 不知道定义为那种方式的接口
    4. Get 传大量查询参数, 不方便的接口, 前端意见很大, 后端接收也不是很方便, 偷懒用 Post 了不少

    我觉得 Get 传参限制太多了, 通常只能携带路径参数 (其实理论上服务器也能接收 Get 请求体), 要是能加一种查询的
    类似 Get + 能发请求体就好了, 其他的问题都是可以解决,最多麻烦点, 慢慢都会好
    fffang
        67
    fffang  
       2022-04-13 13:15:32 +08:00
    业务错误当然是 200+error ,业务错误是没办法通用定义的,你定义一个我看看。
    401,500 当然要用 HTTPCode 。
    xuanbg
        68
    xuanbg  
       2022-04-13 13:16:18 +08:00
    @adoal 没错,我司也是向来运维和业务两套日志,各管各的真是太简单了有木有。某些人学了点规范什么的就忍不住要拿出来显摆,以此找点自信和优越感,也可以理解的。
    seakingii
        69
    seakingii  
       2022-04-13 13:27:01 +08:00   ❤️ 7
    API 接口返回的状态吗,不用 HTTP 状态码 没有任何问题.

    API 接口还不一定用 HTTP 协议传输呢.

    纯粹是技术和商业的问题,上面那些从不用 HTTP 状态码,上升到国家,文化,简直搞笑.
    haochen2
        70
    haochen2  
       2022-04-13 13:31:50 +08:00
    @daimubai 赞同
    horizon
        71
    horizon  
       2022-04-13 13:32:54 +08:00
    @monkeyWie 飞书系统设计很优秀吗
    1000copy
        72
    1000copy  
       2022-04-13 13:34:58 +08:00
    @adoal 赞。
    a62527776a
        73
    a62527776a  
       2022-04-13 13:39:31 +08:00
    401 指的是接口需要鉴权才能访问
    事实上你需要登陆后才能读取数据的接口 不需要登陆也能访问,能理解区别吗?意思是 401 并不是业务层的 code

    曾经有个领导 非过来搞这套 烦都烦死了
    3dwelcome
        74
    3dwelcome  
       2022-04-13 13:42:59 +08:00   ❤️ 3
    我还是喜欢 200 一把梭。

    原因是只要遇到 400/500 这种 HTTP 错误状态码,我就马上能知道是 CDN 或者网关之类出问题了,不是我的业务逻辑部分出问题了。

    你们可以查一下 RFC7231 设置 200 的初衷( The 200 status code indicates that the request has succeeded ),仅仅代表本次网络请求成功,没有任何别的附加实际业务的含义。所有业务相关的内容,请在 payload 里自己处理。
    seakingii
        75
    seakingii  
       2022-04-13 13:43:31 +08:00
    我的建议是面向公众提供的 API 接口,尽量用 restful 规范,大家容易理解,易于标准化.

    组织内部或者个人搞的系统,怎么方便就选择哪种
    raptor
        76
    raptor  
       2022-04-13 13:45:19 +08:00
    简单业务当然没什么问题,越省事越好。

    但是发展到一定程度就会有问题,比如需要上 API 网关,在其中处理一些如监控,日志,告警,流控之类的时候,本来用 HTTP 动词和状态码可以简单处理的事情,变成需要解析 BODY 的时候,你就准备去填自己挖的坑吧。

    当然,如果在可预见的未来,你也不会达到这样的程度,那就随便了——大概率是这样的。
    a62527776a
        77
    a62527776a  
       2022-04-13 13:45:34 +08:00
    不说 restful 标准什么的
    单论用户鉴权相关的 HTTP Status 绝不是 401
    binux
        78
    binux  
       2022-04-13 13:48:58 +08:00
    @3dwelcome 人家原文明明是“请求成功”,网络两个字是你自己加的。
    vayci
        79
    vayci  
       2022-04-13 13:49:40 +08:00
    每次这个问题都会引发大量争论哈哈哈哈哈
    考古贴:《 API 使用 HTTP 状态码还是全部返回 200 》
    https://www.v2ex.com/t/191534
    seakingii
        80
    seakingii  
       2022-04-13 13:56:17 +08:00   ❤️ 1
    楼主想要规范,其实 restful 还有动词的规范:
    put ,patch,delete
    楼主你想不想用?

    用了,有时网络链条中,某些环节对这些动词兼容的不好,
    不用,你怎么不遵守规范呢?
    seakingii
        81
    seakingii  
       2022-04-13 13:57:50 +08:00
    @vayci 因为这是一个对工作影响比较大的事情,而且这个事情从有 restful 规范到目前为止还没有完美解决方案.不断的新人进来,不断的有疑惑
    yolee599
        83
    yolee599  
       2022-04-13 14:04:04 +08:00
    全 http 状态码 200 方便,统一解析 body 再判断。如果 http 状态码和应用状态码一起用还要判断两次,比如 http 状态码为 401 ,有可能是未登录,有可能是 token 过期,有可能是触发风控...
    iyaozhen
        84
    iyaozhen  
       2022-04-13 14:05:55 +08:00
    你要不用 restful 规范我都不说啥了,200 一把梭 坚决反对
    说两点
    1. 监控怎么做?都是 200 ,怎么知道错了
    2. ( nginx )重试怎么做?
    777777
        85
    777777  
       2022-04-13 14:08:52 +08:00
    直接 openapi 一把梭,还能生成文档,服务端客户端代码。
    zhuweiyou
        86
    zhuweiyou  
       2022-04-13 14:12:36 +08:00
    个人全 200, 理由是在 websocket 之类的场景,我仍然需要把 code 放在 json 里.
    ZeroDu
        87
    ZeroDu  
       2022-04-13 14:21:33 +08:00   ❤️ 1
    restful 这东西是真不好用就是了
    Chad0000
        88
    Chad0000  
       2022-04-13 14:25:23 +08:00 via iPhone
    @adoal #58
    很是赞同。业务是业务,http 服务是 http 服务。业务监控自有各种监控中间件。否则哪天不用 http 了或者需要兼容另外一种协议,就完犊子了。
    Kinnice
        89
    Kinnice  
       2022-04-13 14:25:27 +08:00   ❤️ 1
    @iyaozhen 虽然我也反对 200 一把梭,但是你这两点貌似都没太大关系吧,
    监控:
    1. 业务监控,那解析 body 是应该的,
    2. 链路监控,业务出问题和你链路有啥关系?
    3. 混合监控,就算你看到了 4xx/5xx 你不解析 body ,能准确反应出原因? httpcode 可没这么全
    nginx 重试:
    业务出问题了,你网关重试个啥? 比如我 post 添加一条数据,失败了,你 nginx 还帮我重试一下?
    iyaozhen
        90
    iyaozhen  
       2022-04-13 14:25:53 +08:00   ❤️ 1
    @adoal
    @xuanbg

    监控的事情我说下个人看法

    业务要监控这个是肯定的。但这就需要一个规范,不管是分开打日志还是怎么的。
    http 状态就是一个规范,比如我是公司做网关的基建部门,公司几万个研发,你让 json 里面字段怎么约束?这个人用 code xxx ,那个人 status xxx ,我无法监控呀。但有个 http 状态码 5xx ,我就能知道这个业务挂了,可以进行一些预案。至于定位又要扯到 logid 串联了。

    当然这也是搂底,业务自己的日志还是得配置关键字接口,两者结合。
    pengtdyd
        91
    pengtdyd  
       2022-04-13 14:26:01 +08:00
    200 一把梭 坚决反对!!!
    20X 、40X 、50X 这些是 HTTP 状态码和业务状态码混淆在一起怎么做监控???
    错误码设计可以参考阿里巴巴《 Java 开发手册》错误码的制定原则:快速溯源、简单易记、沟通标准化。
    1 )错误码必须能够快速知晓错误来源,可快速判断是谁的问题。
    2 )错误码易于记忆和比对(代码中容易 equals )。
    3 )错误码能够脱离文档和系统平台达到线下轻量化地自由沟通的目的。
    iyaozhen
        92
    iyaozhen  
       2022-04-13 14:30:00 +08:00
    @Kinnice
    我说的是网关层面的搂底监控。这种时候各个业务 json 都不一样,解析不了,而且影响性能。有个 5xx 监控会好很多

    nginx 重试
    说的是幂等的重试,比如 GET 、PUT ,当然如果 POST 一把梭就做不了了。
    Kinnice
        93
    Kinnice  
       2022-04-13 14:33:10 +08:00
    这个问题还有个孪生题目: 为什么要区分不同的 HTTP 请求方法?(hhhhhhh)
    jjwjiang
        94
    jjwjiang  
       2022-04-13 14:34:10 +08:00
    @daimubai 同意,真不知道搞技术的也这么多一根筋的。

    拿 400 和 422 举例,422 可以很容易的覆盖一部分业务错误,所有参数上的不合法都可以归到 422 里,对监控更容易,跟别的合作伙伴做对接也更简单。

    比如 request 定义是
    { n:int, s: string}
    而 n 要求大于 0 ,s 要求不能为'',那么
    {'1'}
    就会对应到 400
    {n:'1',s:1}
    {n:-1,s:''}
    对应到 422
    而 n:1998 会造成业务上出错,那自然是以 200+message 返回

    界限很清楚也很好用,422 我就去检查参数值,400 就检查参数格式,而 4 开头的都会被浏览器认定为 client 错误,事实上也确实是作为 client 的调用方有错误,不挺好吗?

    rest 规范你觉得不合理就选择使用就完了,全盘否定或者全盘肯定都是不现实的。
    adoal
        95
    adoal  
       2022-04-13 14:37:09 +08:00
    @iyaozhen 屁股决定脑袋。你所谓的对业务的监控,是指想知道业务挂了,这个问题本来就属于基建。我也说了,如果业务系统里发现有基建问题,硬生生抓住包成一个 200 抛回给调用方,这个我也不能接受的。但很多莱塞特福原教旨主义者想要做的是把业务逻辑层面的错误也给放到 HTTP 状态码里,比如一个大学生离校系统里要去查学生在各个单位的业务是否已结清,我一个图书馆系统的接口发现还有书没还的时候,给他返回 HTTP 200 再加一个 JSON 表示业务层面这个操作不成功,但我的系统没挂,调用方传进来的参数也符合 schema ,权限也对,所以在 HTTP 层面我认为没问题,不应该返回错误码……有人说这样不清真,应该改成在 HTTP 码里把这个当“错误”来返回,不能塞进 200 的 JSON 里。这不是扯鸡巴蛋吗。总不会有人为了方便监控离校系统调用图书馆系统接口时的业务逻辑错误率而想把我千奇百怪的业务错误码从 JSON 里提出来放到 HTTP 状态码吧。
    Actrace
        96
    Actrace  
       2022-04-13 14:43:54 +08:00
    我觉得应该用 TCP 的状态( etc.. LISTEN ,SYN_SENT ,ESTABLISHED...)来表示。这样比较底层,权威性更高一些。
    HTTP 协议的状态码都已经是最顶层了,不权威的。

    ...说笑的。

    既然 https://coolshell.cn/articles/22173.html 里说到 HTTP 是协议的一种,STATUS 属于协议的部分,而承载的 BODY 才是业务内容。那么我认为用于处理业务问题的业务协议及其内容,与 HTTP 协议是两种不一样的东西,HTTP 协议的所有内容应该专注于它本身需要专注的部分。

    比如 STATUS 503 是服务不可用,服务不可用是服务器硬件资源的问题,而不是业务不可用。尽管业务和服务器状态本身是互相关联的,但是我们应该尽可能去解耦,让运维团队专注解决硬件资源问题,业务团队专注解决业务问题。

    虽然大多数情况下,你一个人就是一支军队,所以所有问题都自己解决的话,倒不是有必要区分得那么明显了。

    所以还是看业务规模吧,以上个人观点仅供参考。
    3dwelcome
        97
    3dwelcome  
       2022-04-13 14:44:43 +08:00
    @iyaozhen “你要不用 restful 规范我都不说啥了,200 一把梭 坚决反对
    1. 监控怎么做?都是 200 ,怎么知道错了”

    监控可以另外写 API 。我们的业务不仅仅是 HTTP 协议哦。HTTP 协议只是业务传输载体之一,还有 TCP 封装和 websocket 封装,底层调用的业务逻辑代码,是同一个模块。
    james2013
        98
    james2013  
       2022-04-13 14:45:14 +08:00
    反正客户端方面,接口方面区分状态码就很烦
    客户端哪里知道后台接口使用 4xx,5xx 呢?比如后台在某些 4xx,5xx 里是框架自带的错误码,而不是固定的 json 对象
    还不如直接返回 200,在统一的返回对象里统一处理和提示
    jjwjiang
        99
    jjwjiang  
       2022-04-13 14:50:50 +08:00
    @james2013 你这说法就不太对了,显然在现代前端里 promise 广泛使用的情况下,catch 比 if(res.code ==200)的语义化和代码结构更佳。
    lolizeppelin
        100
    lolizeppelin  
       2022-04-13 14:56:44 +08:00
    一般是代码设计有问题,有错没错的返回混了,只能用 result 里的 code 判断了

    正确设计是所有错误以 raise

    http 返回的部分加一个 translation 把内部 Error 翻译成 Http Error

    最好 rpc 也能把 raise 的异常传递
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2957 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 03:43 · PVG 11:43 · LAX 19:43 · JFK 22:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.