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

后端 response code 该怎样返回?

  •  
  •   hlayk · 42 天前 · 2369 次点击
    这是一个创建于 42 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前提:前后端定义了通用的数据结构包含 data,mseeage,code,success 这几个基本字段用来去接收后端接口的数据。

    场景:某一接口客户端发出的请求出现参数或后端校验等业务错误

    问题:后端 http 层的 response code 应该返回什么? 200 还是非 200 ?(呆过的不同公司有着不一样的习惯)

    问题来源:主要是用的网络请求框架( retrofit ),对于小于 200 或者大于等于 300 的 response code 直接抛了异常,但我并不想对这异常再进行解析 HttpException 中的 response body 解析出上述的数据结构,所以我拦截了 response 改了 response code 为 200 。这样的话,我对于 response code 无论是什么,我都可以同样的对象解析。

    第 1 条附言  ·  42 天前
    对于后端 response code 返回特定的 4xx 5xx 我是赞同的。只是不想对那种 非 200 的 response,在 catch 中做额外的解析。
    [代码示意]( https://s3.bmp.ovh/imgs/2021/10/776467738425d9c4.png)
    44 条回复    2021-10-21 11:19:07 +08:00
    kile
        1
    kile   42 天前   ❤️ 3
    code 是业务码,是前后端进行约定的东西。不要用和 http code 一致的方式,这样会让人混淆。。
    Jooooooooo
        2
    Jooooooooo   42 天前   ❤️ 4
    0 成功, 去拿 data 中的内容

    非 0 异常, 展示 msg 中的内容
    securityCoding
        3
    securityCoding   42 天前
    success 没看懂 ,其他三个够用了
    SingeeKing
        4
    SingeeKing   42 天前   ❤️ 1
    遵从 REST 的应该是 400,不遵从就随缘来。。
    CodeCodeStudy
        5
    CodeCodeStudy   42 天前   ❤️ 1
    code,用 1 来表示成功,大于等于 1000 的整数表示错误码,之所以用 1 是因为弱类型语言中 1 == true,让人一眼就认为是表示肯定的意思,用 1000 以上的整数是为了避免和 http 状态码混淆
    b1t
        6
    b1t   42 天前 via iPhone
    我今天也把代码里的大于 300 抛异常给注释掉了,等个讲解
    hingbong
        7
    hingbong   42 天前 via Android   ❤️ 1
    我们是遵循 HTTP 定义,异常都是 4xx 5xx,当然,封装的结构也有详细的错误码
    jerryshao
        8
    jerryshao   42 天前   ❤️ 1
    后端参数校验错误应返回 400 HTTP respond code 。
    message 应返回有帮助性的错误信息,比如请求参数里的 XXX 字段长度不能超过 YYY 等等。
    code 字段可以是自定义错误码,一个自定义错误码对应一个异常。

    Retrofit 抛异常是对的,前端应该 catch 这个异常并做相应处理。
    比如 catch 异常并分析 respond 是 400,打印日志,看是否需要提示前端用户参数错误或加强表单验证。
    如果 catch 异常并分析 respond 是 500,打印日志,上报监控指标,配置 client 进行请求重试。
    hlayk
        9
    hlayk   42 天前
    @jerryshao 后端返回是没问题 retrofit 抛异常也对。只是后端对于正确与否的数据都是同样的封装 所以 retrofit
    将异常给抛出来需要做额外的解析 如果后端返回的是 200 自定义的数据结构 中 code 再指定的话 那样就不需要写额外代码了,我只需解析一次返回对象 针对不同业务 code 做不同的处理
    hlayk
        10
    hlayk   42 天前
    @securityCoding code 太具体 不够抽象 大部分业务只关心成功 失败最多显示下 message
    Hyvi
        12
    Hyvi   41 天前 via iPhone   ❤️ 1
    非 200 。以后监控更方便搞。自定义的 code 最好自定义的错误。
    IvanLi127
        13
    IvanLi127   41 天前 via Android
    在 header 传递业务层的 code 。
    jerryshao
        14
    jerryshao   41 天前   ❤️ 1
    @hlayk 可以是可以,但是大家在这里建议的是业界比较认可的做法。

    如果返回 200,前端根据 code 字段做相关处理,那后端做可用性相关的监控就比较让人头疼。
    不知道你们有没有对后端的 canary test,中文好像叫拨测?将来持续测试后端 api 的话,正常来说判断 api 是否成功就是使用这些 http respond code 。如果后端都是返回 200,那相关的测试也无法从 http respond code 获知是否成功,需要解析里面的自定义 code 才知道。
    hlayk
        15
    hlayk   41 天前
    @jerryshao 是的 我认为后端这样返回是对的 只是我自己代码里加了个拦截器 把所有 response code 都改写成了 200 这样方便自己统一的处理 但是写完感觉怪怪的
    oxromantic
        16
    oxromantic   41 天前   ❤️ 2
    想想 http 的 code 有啥作用就能想通怎样用最好

    举例来说,http 400 表示错误的请求,404 很多框架表示服务找不到不可达,这些都是属于预期之外的错误,在评估服务健康度的时候都需要采纳,如果混用,譬如把 404 作为常规业务逻辑(离谱点譬如搜索找不到就返回 404 ),就会产生很大的功能混淆,如果再集成一些网络日志框架(听 X 之类),简直就是业务和标准错误混合的灾难

    可以参考下百度云 api 的设计,虽然百度云很流氓,但是不可否认 api 定义还是有参考价值的

    另外我不同意上面说的持续测试只采用 http response code 来判断,这种属于没经历过 http 时代电信的鞭打以及没用过 cdn,永远不要相信 http response code 能代表你业务的状态,否则就是给项目埋雷
    tiedan
        17
    tiedan   41 天前
    code 返回 200,code 用特定错误代码,网关层写规则根据 code 转换成 4xx or 5xx
    xuanbg
        18
    xuanbg   41 天前
    实际上有 success 表示调用是否成功的话,code 基本没啥用。因为你 success 是 false,都直接输出 message 了。有 code 啥事?
    xuanbg
        19
    xuanbg   41 天前
    @oxromantic 对的,http response code 只能代表 API 服务本身的状态,而不能代表 API 服务上的业务的状态。把这两个状态混起来用虽然也能用,但遇到问题就很难定位到底是哪个层面的问题了。
    yidinghe
        20
    yidinghe   41 天前 via Android
    协议层的问题和业务层的问题不要混淆吧,不然的话例如前端得到 404,可能是后端框架因为配置错误根本没将请求转发给业务层,会给排查带来不便
    Rache1
        21
    Rache1   41 天前
    看前端,可以让前端传个指定 header 来给所有响应都返回 200,默认按照 HTTP CODE 返回。

    实际 response 里面的 code,我之前的做法都是三位 HTTP CODE + 三位业务 CODE 。 比如 400001,400 就是对应 HTTP CODE 中的请求参数有问题,001 就是可能是某个字段或者某个过程没有校验通过。
    2i2Re2PLMaDnghL
        22
    2i2Re2PLMaDnghL   41 天前   ❤️ 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 区分出来
    oxromantic
        23
    oxromantic   41 天前
    @2i2Re2PLMaDnghL retrofit 你居然让换个正常点的框架?类似 ios 的 alamofire,都是 top1 的框架,都不建议在非 200 的 http status code 里处理业务逻辑
    hlayk
        24
    hlayk   41 天前
    @oxromantic 大家又不是都是搞移动端的 不知道这些库也正常
    abcbuzhiming
        25
    abcbuzhiming   41 天前
    关于 code 返回什么,一直有争议,有人认为就应该用 http 的 status code,所以他们返回 200 ;而另外一群人比如我就认为 code 是业务码,和 http status 无关,正常下就是 0,非 0 就是错误,并且附带错误信息 msg 。
    lewinlan
        26
    lewinlan   41 天前 via Android
    业务内的异常就装在 code 里,http 给 200 。
    网络,框架等非业务的异常,才用 400/500 的 http 。

    把资源装进 data,这个事情就已经不 REST 了
    2i2Re2PLMaDnghL
        27
    2i2Re2PLMaDnghL   41 天前
    @oxromantic 这个建议是为了 HTTP 以外的一些协议没有 status code 所以将 HTTP 降级。这就好比因为很多网站不支持 bbcode 就要求现在在用 bbcode 的网站一律不允许使用 bbcode 一样可笑。
    oxromantic
        28
    oxromantic   41 天前
    @2i2Re2PLMaDnghL 你搞错了,这些 status code 并不是你应用独占的,和容器抢这些 status code,就会给前端引入不确定性的混乱,而没有个前端定义一个可以直接判断属于业务数据的基础规则
    2i2Re2PLMaDnghL
        29
    2i2Re2PLMaDnghL   41 天前
    @oxromantic 那就更诡异了,容器为什么要抢 status code ?它连 HTTP 都不 aware
    penll
        30
    penll   41 天前
    code 直接英文字母,方便后端定位问题。
    message 只是给用户看得友好信息
    oxromantic
        31
    oxromantic   41 天前
    @2i2Re2PLMaDnghL pcf/k8s 都会啊,可以了解下
    unco020511
        32
    unco020511   41 天前
    两种都可以,看你们怎么理解,可以把 http 单纯当做一个数据传输协议,只要数据传输成功一律 httpcode200,然后定义自己的业务 code.同时因为 httpcode 也是语义化的,也可以使用仅使用 httpcode 一套来表示传输及业务状态
    ychost
        33
    ychost   41 天前
    code 建议用字符串,这样方便两个调试,httpCode 一律 200
    2i2Re2PLMaDnghL
        34
    2i2Re2PLMaDnghL   40 天前
    @oxromantic 首先,PCF 似乎是 VMWare 的多个不同的东西的品牌名称?具体没搜到。k8s 是编排工具而不是容器。
    其次,各类 load balancer 看上去也并不会抢 status code,而是尝试中间捕获 status code 来判断服务健康状况来安排重启和替换请求,这种情况下会修改的可不止是 status code,而是整个响应都会被替换。
    xingheng
        35
    xingheng   40 天前
    @Jooooooooo #2 我要是看见谁用 0 标识自定义 code 为成功的话一定往死里骂,int 的默认值(在很多语言里很多都)是 0,本来就是取个 int 的事情非要我区分到底是因为服务器本身返回的傻逼 0 还是 code 值取不到用了 int 默认值。
    oxromantic
        36
    oxromantic   40 天前
    @2i2Re2PLMaDnghL pcf 是比较早的商业容器实现,大概被 vmware 收购了,具体没了解,既然你提到整个响应都会被替换,这就是我之前描述的场景,你以为的业务 response,实际已经被替换了,所以不能光靠 http status code 来处理业务,还需要加额外的逻辑,但既然加额外的逻辑,何必还抱死 http status code ;另外,我所谓的容器是广义的,譬如远古的 war 跑在 tomcat 里,那么 tomcat 就是 war 的容器,tomcat 自己也会用到 http status code 表达自己的状态
    Jooooooooo
        37
    Jooooooooo   40 天前
    @xingheng 你担忧的问题在这里不是问题. 用了就知道.
    2i2Re2PLMaDnghL
        38
    2i2Re2PLMaDnghL   40 天前
    @oxromantic 替换应是对前端透明的,不需要额外逻辑。
    Tomcat 算是混合了一个编排工具?
    编排工具如何返回它自身的信息应当是可以自定义的,而不是埋暗雷(但暗雷见得多了,Flask 也暗雷)。不过现在问题是科技树还没点到动态编译语言。

    当然,如 #26,放 data 已经不 REST 了,本来的处理上就是 body 就是全部内容或者没有内容,甚至,尽管不那么典型,这个 URL 逻辑上是可以 cd 进去的(类似 WebDAV )。
    应当将这种状态和其他协议的 code/data 状态进行对应。gemini 更诡异一点(
    xingheng
        39
    xingheng   40 天前
    @Jooooooooo #37 不是所有语言都支持 optional type,后端写的接口需要考虑各种语言的使用场景。
    bthulu
        40
    bthulu   40 天前
    非对外公开给其他部门或其他公司使用的 API,一律不做任何处理,什么 status, code, msg 都不需要,逻辑成功就返回对象,失败就返回异常信息。前端框架统一对 4XX 错误做下处理,其余什么也不要做。简单就是美
    zachlhb
        41
    zachlhb   39 天前 via iPhone   ❤️ 1
    http code 永远返 200,然后错误码用自己数据的 code 区分,为什么不用 http code,因为一些前端框架拿不到非 200 的响应数据,非 200 响应在前端来看就是异常,直接走前端框架的异常处理了
    bug123
        42
    bug123   39 天前
    0 表示成功
    非 0 表示错误码,message 作为额外的补充
    hlayk
        43
    hlayk   39 天前
    @zachlhb 是的 问题就在这里 返回的响应结果本身就是同一个数据结构 但是因为 http code 非 200 导致框架抛出异常 我这里就需要额外捕获异常 再从异常中解析 response 这在我这里看来就是多此一举 但是我也没有合适的理由去说服后端去改 http code 所以加了拦截器 将后端所有的 http code 改为了 200 以便统一处理
    flyingfz
        44
    flyingfz   39 天前
    http 协议相关 的状态码, 交给 status code . 例如 无权限 403, 找不到资源 404,参数错误 400 之类.

    业务的状态码交给 code, 例如登陆失败, 扣款失败。注意, 此时 status code = 200 .
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2681 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 12:32 · PVG 20:32 · LAX 04:32 · JFK 07:32
    ♥ Do have faith in what you're doing.