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

采取 RESTful 风格的 api 是否应该对结果包一层?

  •  
  •   h82258652 ·
    h82258652 · 2019-10-21 23:18:13 +08:00 · 25577 次点击
    这是一个创建于 1862 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RT,今天公司的新项目开始对接,app 端的一看我这接口就吐槽我。让我改成如下这种: { "code": 200, "message": "", "data": xxx }

    但我觉得首先这 code 肯定是多余的,可以直接从 http 状态码里面读取。之前也看过 twitter 的 api,也没有说包一层,200 的话那就直接返回 data 了。 公司项目我就忍忍算了,毕竟人家老员工。但后面有自己项目的话,还是想弄标准一点。不知道一般来说,大家是怎样实现?

    305 条回复    2019-10-24 10:47:14 +08:00
    1  2  3  4  
    qlhai
        101
    qlhai  
       2019-10-22 10:29:57 +08:00
    此处是业务 code,跟 HTTP 那个还是不一样的啊
    Narcissu5
        102
    Narcissu5  
       2019-10-22 10:30:53 +08:00
    @Amayadream
    @pkoukk 登录失败和登录失效压根就不是一个场景下的问题
    你们就说说你们监控了 code 没有
    uxstone
        103
    uxstone  
       2019-10-22 10:32:36 +08:00
    如果是用 Spring 的话,一个注解就能搞定
    想多包装一层就加注解,不想包装就不加注解
    markgor
        104
    markgor  
       2019-10-22 10:35:03 +08:00   ❤️ 2
    @chendy http 的 code 只能代表請求的結果吧?
    返回數據裡的 code 是代表業務的執行結果,根本是兩回事,
    不要動不動就說別人不懂 http 的 code,只是別人想的比你多一步。

    eg:
    在線預訂門票的栗子,
    對方業務系統規定:
    當 code 為 9999 時,代表對方系統維護中,所有請求 30 分鐘後重試。
    當 code 為 1XXX 時,違反門票業務約定( XXX3 位數代表著不同的約定)
    當 code 為 2000 時,代表著訂單提交成功
    當 code 為 3XXX 時,代表處理失敗,違反直連約定,具體根據 XXX3 位代表不同的結果,有可能是重複單號

    直連約定上,當 http 服務不可用(返回非 200,需要每隔 5 分鐘進行重試,超出 10 次後線下聯繫處理。)
    當返回 9999 時,代表對方系統維護
    兩個是不一樣的概念,你為何可以那麼優秀地認為別人是多此一舉呢?如果你用 http 的狀態碼來表示,拍錯的時候不會導致連業務信息處理出錯或 http 請求出錯都區分不了嗎?

    另外“类似的道理,还有用参数指定返回格式的人,大概是不知道 Accept 头(可能也不知道 Content-Type”
    給個例子你,
    甲方對接了很多套酒店系統,有些系統返回的是 xml,有些返回的是 json。
    然後乙方和甲方對接,數據返回根據甲方提供的 api 均為 json,
    但是由於很多實時請求是乙方 發送請求給甲方 甲方 再發給酒店,(等於甲方做數據交換),
    這個時候甲方在返回給乙方的數據架構上,加上數據具體格式,有問題嗎?
    response->{
    code:2000,
    type:'json',
    data:'{code:xxxxx,data:xxxxxxxxxxxxxxx}'
    }
    你肯定會說為什麼甲方不解釋了酒店數據,然後直接返回給乙方。
    那是因為甲方是做數據交換服務,在數據改動最少的範圍內傳遞給乙方。
    cmobiooo
        105
    cmobiooo  
       2019-10-22 10:35:15 +08:00
    @icris 我前公司在客户端的 API 里是这么做的……
    Narcissu5
        106
    Narcissu5  
       2019-10-22 10:37:21 +08:00
    @eason1874 撞库或是社会工程学爆破,能不能嗅探到账号是否存在差别就太大了
    passerbytiny
        107
    passerbytiny  
       2019-10-22 10:37:27 +08:00
    @yamedie #75
    @pkoukk #81
    @Amayadream #86
    三位一看就没设计过错误代码,根据登录接口的不同返回情况做不同的后续交互处理,这是登录功能自己的事,并不是全局通用规则,所以这些不同错误情况的代码,应当放到 data 中,而不是 code 中。
    reus
        108
    reus  
       2019-10-22 10:38:48 +08:00 via Android
    @chendy 你大概不知道以前有 http 劫持,http 状态码不是 200 就直接给你“智能”处理了。当然现在普遍 https,很难劫持了。所以接口不依赖 http 状态码,是有历史原因的,并不是别人不知道。
    ClericPy
        109
    ClericPy  
       2019-10-22 10:40:41 +08:00   ❤️ 1
    第一句就提到是对接了, 说明对已有项目规范不了解, 先去看一下公司 API 设计文档吧, 谁知道 code 说的是什么 code, 有问题最好当面提出来, 跑这里吐槽只会恶心自己, 有些前端就是需要详细 code 来判断操作结果, 上面某人说的 99% 也不知道从哪搞来的多大的样本

    上面还有一大群说 status code 用来分析日志更方便, 难道不知道日志系统里, access 日志和 server 日志不是同一个用途的吗, 后者自定义日志用来分析的, 前者也不是用来看这个的, 自己公司不用不等于别的公司用不着, 还是具体问题具体分析吧, 简单地说, API 规范这东西和产品经理多问问, 免得写出来给你砍掉

    细分错误码, 甚至正确的返回码, 方便调试也提高用户体验, 很多时候用户不关心, 但是调试关心, 类似微信公众号错误码 (虽然他们家的也不咋滴)
    https://iot.weixin.qq.com/wiki/document-2_14.html
    ==============================
    错误码 错误信息 描述
    0 ok 成功
    -1 system error 系统错误
    100001 not exist 查询请求不存在
    ==============================
    haha370104
        110
    haha370104  
       2019-10-22 10:46:02 +08:00
    只有一个问题,也不是杠

    比如有个接口在查询不到数据报错的时候,直接用 httpcode 404 报错?

    那前端监控应该怎么加呢? 4xx 错误有的是预期错误(比如账号不存在)有的可能是非预期错误(比如手抖或者 server 问题真的 url 404 )
    miniwade514
        111
    miniwade514  
       2019-10-22 10:46:28 +08:00
    @reus 不用大概,是肯定不知道。然而他不去了解就说别人蠢,前途无量。
    reus
        112
    reus  
       2019-10-22 10:46:32 +08:00 via Android
    另外,如果需要在非 http 承载调用,例如直接 tcp 或者其他 rpc 框架,那还是需要信封的。如果已经有信封,那不需要改动就能迁移,调用端也能无缝兼容。

    不要太过依赖 http,世上并不是只有 http
    losephsky
        113
    losephsky  
       2019-10-22 10:47:56 +08:00
    支持业务 code
    reus
        114
    reus  
       2019-10-22 10:48:03 +08:00 via Android
    @miniwade514 年轻人不知道一些旧事,可以原谅…
    markgor
        115
    markgor  
       2019-10-22 10:51:23 +08:00
    @Narcissu5 我看你說的,側重點在於監控方面吧?
    我之前對結果其中一家數據交換公司,他們 PM 每月都會發送一份報表給我們,
    其中包括 接口請求成功率,接口預定成功率
    接口請求成功率 是他們考量他們自身服務的標準,其中包含簽約時候的 sla。
    接口預定成功率 這個是考量他們系統和酒店系統的服務標準。
    實際上除了這兩份報表外,還有其餘很多報表,大致是分析推送數據成功率,延遲等等。

    你說 response 返回多一層 code 無法監控,
    那請問別人為何又能監控,而你無法監控?
    index90
        116
    index90  
       2019-10-22 10:56:00 +08:00   ❤️ 5
    每次有人在纠结返回码问题的时候,我就贴出这个链接,然而每次都没有人看。
    https://cloud.google.com/apis/design/errors

    Google APIs must use the canonical error codes defined by google.rpc.Code. Individual APIs should avoid defining additional error codes, since developers are very unlikely to write logic to handle a large number of error codes. For reference, handling an average of 3 error codes per API call would mean most application logic would just be for error handling, which would not be a good developer experience.

    试想想,如果下游服务返回一个错误码给你,你有两个选择
    1. 识别并处理这错误码:
    if code == some_error_code {
    // do something
    }
    2. 不处理透传返回码:
    if code != 0 {
    return code
    }

    第一种,如果你错误码很多,那你就要写大量的错误码处理逻辑(每个接口)
    第二种,透传到上层,那上层遇到的错误码可能性就越多,越不想处理。那么错误码的意义在哪里?出错是,方便定位?那一个字符串类型的 error detail 是不是表达能力更强?
    Amayadream
        117
    Amayadream  
       2019-10-22 10:56:52 +08:00
    @Narcissu5 #102
    核心业务都需要做错误码监控和告警的,不熟悉可以去了解一下。

    @passerbytiny #107
    我觉得你可能没出校门。
    star7th
        118
    star7th  
       2019-10-22 10:59:04 +08:00
    没法看了,这种做多几个项目就能明白的事情为什么会引起这么多争议。
    因为偶尔情况下,前端或者 app 需要根据状态吗来做业务逻辑处理啊。http code 是系统层面的,代表请求本身成功,不应该跟具体业务耦合。
    比如说,获取用户资料信息,万一用户在获取的时候 token 过期呢,前端就可以根据返回状态吗引导用户重新登录。
    这样做固然并不是绝对的需要,但很明显这样包一层更方面以后传递信息和自定义更多异常处理。
    Narcissu5
        119
    Narcissu5  
       2019-10-22 11:00:12 +08:00
    @markgor 不是无法监控,而是成本非常高

    如果你有了解过 Http 协议的话就会明白,分析 Http Header 很容易,而分析 Http body 是很耗时的,实际上对于简单的应用来说,相当一部分的 CPU 时间用在了序列化 /反序列化上。如果你的接口支持通过 Accept 指定不同格式的返回消息那问题就更加复杂得没边了
    maomaomao001
        120
    maomaomao001  
       2019-10-22 11:00:27 +08:00
    @helone 举个最简单了例子,
    比如业务就是, 登录的时候,账号错误 focus 到账号输入框并变红,密码错误 focus 到密码输入框并变红(虽然现在不会单独搞这种错误了) , 你只给个信息不够呀,是不是还得有标志位???
    dreamer1998
        121
    dreamer1998  
       2019-10-22 11:00:33 +08:00
    我一般会包一层,因为很多时候会有很多业务异常码,http 状态码显然表示不出来
    AppxLite
        122
    AppxLite  
       2019-10-22 11:05:00 +08:00
    code 是业务代码。以前也不喜欢,觉得没必要。现在感觉也挺好的,感觉规范一点
    ```javascript
    {
    code: 200,
    msg: "ok",
    data: {}
    }
    ```
    Narcissu5
        123
    Narcissu5  
       2019-10-22 11:11:41 +08:00
    天哪,登录时不返回详细的报错信息不应该是常识么
    eason1874
        124
    eason1874  
       2019-10-22 11:13:07 +08:00
    @Narcissu5 #106 这个看你的业务类型,有的业务用户名本身就会作为用户内容的一部分暴露在外面,但就算是去掉这个,也只是把用户不存在的错误改成用户名或密码错误而已,还有大把登录提示。
    beyondye
        125
    beyondye  
       2019-10-22 11:13:20 +08:00
    程序员都是以为自己比谁都牛逼的一群人
    markgor
        126
    markgor  
       2019-10-22 11:15:11 +08:00
    @Narcissu5 我明白你的意思,但是成本的高低是看業務的需求,
    當業務是存在此方面的需求,成本就不會覺得高。
    當業務對於這方面需求度不高,成本自然覺得高。

    但是和你在上面說了三次 無法監控 ,
    這真的是有點誤導啊。

    你如果說在現有架構上增加監控,那的確如你所說,會消耗性能,並且業務量大的時候會對業務造成困擾。
    但是建議你可以了解下旁路設備,增加旁路設備後對數據進行監控,就算業務量再大,頂多就是旁路設備處理存在延時,可監控報表維度一般都按小時 /天 /月 來統計,這點延時根本不足以影響數據準確度;而且旁路設備就算掛了,對業務一點影響都沒有。

    另外交換機的端口鏡像,也是實現旁路的一個好設備。
    eason1874
        127
    eason1874  
       2019-10-22 11:15:46 +08:00
    @Narcissu5 #123 不是常识,是你们想象出来的,说国内的厂商你可能觉得他们知识水平不够高,不信你去登录 Google 或者 Microsoft 看看,用户名不存在他们会提示你不存在。
    Narcissu5
        128
    Narcissu5  
       2019-10-22 11:22:30 +08:00
    @markgor 监控不光是看看而已啊,nginx 也好 hystrix 也好这些熔断都是根据 httpcode 来的
    vjnjc
        129
    vjnjc  
       2019-10-22 11:24:57 +08:00
    @fanyingmao #29 哈哈,这个很随意的,要是在定规范的时候你提,或许就变成 0 是 ok,1 是 fail 了。现在规范都定好了
    qwab16
        130
    qwab16  
       2019-10-22 11:28:26 +08:00
    若是错误处理,我司是 http 500 然后再返回中定义具体错误信息
    markgor
        131
    markgor  
       2019-10-22 11:28:50 +08:00
    @Narcissu5 你既然知道熔斷是根據 http code 進行,那你怎麼還主張通過 http code 來代替 response 的 code 呢?
    歸根到底就是兩套不一樣的 code,
    非要把它們弄到一起,
    項目小的話還沒影響,
    項目大了的話不就搞到定義模糊嗎?
    hantsy
        132
    hantsy  
       2019-10-22 11:33:02 +08:00   ❤️ 2
    @h82258652 你的观点没错。

    应该尽可能用 HTTP 语义来描述你的 API ( URI,Method,Status Code )。

    很多人搬出一些国内知名公司的 API 如何如何, 我只能说,那些公司把你们带歪了。

    REST API 设计质量评估,可以参见 Richardson Mature Model ( Google 搜索)。从这个角度看,国内知名大公司的 API 绝大部分根本就不是 REST (虽然他们的文档写的是 REST API 指南等),充其量就是用 HTTP 协议而已,看起来和以前 SOAP 一样乱。

    如果你想好好设计可用性高,可读性强的 API,参考 Github API,HeroKu,Microsoft 的 API 设计(虽然这个也被 REST 之父骂得狗血淋头,但比国内大公司的设计,不知道甩出几条街)。
    fengci
        133
    fengci  
       2019-10-22 11:36:07 +08:00
    不同的错误 code 前端有时候不是还需要做交互操作吗? 你们有错误就报不做交互的吗?
    linxb
        134
    linxb  
       2019-10-22 11:37:01 +08:00
    我也觉得包一层是脱裤子放屁,多此一举,我的做法是,非成功的请求,后端抛出统一的异常,前端如果捕获到异常,直接展示 message 即可,如果没有异常,就直接处理返回的数据
    markgor
        135
    markgor  
       2019-10-22 11:39:05 +08:00
    @hantsy
    所有的設計指南都是基於理想狀態進行描寫的。
    全世界的業務都不是一成不變的,導致不同的公司就算處理相同的業務也存在不同的流程。
    這個就類似於 社會主義 和 特色社會主義 的區別。
    如果你真要什麼簡潔,那還不如直接逗號替換大法?

    菩提本無樹明鏡亦非臺本來無一物何處惹塵埃
    lazyfighter
        136
    lazyfighter  
       2019-10-22 11:40:56 +08:00
    我建议采用 http-code,我之前做网关的时候碰到一个项目就是自己包了一层,无论怎么样都是返回 200,但是实际的 code 是 response-body 里面包着呢,导致我们这边的监控基本无用,但是他们自身又很难发现问题,我的经验一般对外 http 服务出问题,最优先会在网关层的 httpcode 以及 rt 时间体现
    hantsy
        137
    hantsy  
       2019-10-22 11:42:03 +08:00
    @linxb 异常有 Problem API 和 Error API 标准,只是不怎么流行。Spring hateoas 集中了 一种 Error API 标准(自动转化的)。不过最近 Spring hateoas 版本飙升到 1.0,API 变化很大,又需要更新知识了。
    qza1212
        138
    qza1212  
       2019-10-22 11:43:15 +08:00
    其实核心问题是,你的接口返回的数据类型和结构是否一致
    mikicomo
        139
    mikicomo  
       2019-10-22 11:45:32 +08:00
    @Narcissu5 #49 封装之后怎么不能做监控了...后端主动抛出业务异常日志,包装下返回给前端,然后全链路日志会捕获啊
    markgor
        140
    markgor  
       2019-10-22 11:51:26 +08:00
    @lazyfighter
    主要問題還是取決於監控粒度的大小。
    如果監控內容只是需要成功或失敗,那複用 http code 的確簡單省事。
    如果監控內容是需要區分請求成功率和業務執行成功率時,
    明顯 http code 無法進行有效區分。

    還有,在後端和後端的交互中,
    如果遇到 5XX 的錯誤,基本會進行重發請求,
    如果是遇到了 200 成功,response code 提示錯誤的,基本不會進行請求重發(具體看 code 的定義)。
    MakeHui
        141
    MakeHui  
       2019-10-22 11:51:43 +08:00
    @markgor 前面的老哥已经和他解释的很清楚了,这哥们非要无理争三分,建议赞同他的说法让现实狠狠打他的脸
    workspace
        142
    workspace  
       2019-10-22 11:53:39 +08:00   ❤️ 1
    纯 API 需要包一层,不然后端异常返回的错误类型 前端无法捕捉,举例:

    接口: /api/user/profile 需要登录

    登录访问返回:
    {
    "data": {"username":"xiaoming","age": 10},
    "msg": null,
    "code": 1000
    }

    未登录访问返回:
    {
    "data": null,
    "msg": "无效的认证",
    "code": 1002
    }

    当接口里逻辑有异常访问返回:
    {
    "data": null,
    "msg": "KeyError user has no ....",
    "code": 1100
    }

    当接口挂了的时候访问:
    500 Internal Server Error




    后端有一个最终的 catch error 返回的数据永远是 data msg code 三个字段

    前端和后端已经约定好:
    1 只要返回 200 我认为服务正常,返回绝对是 data msg code 三个字段,如果 code !== 1000 alert(msg) return 否则认为此次请求正常
    2 只要返回非 200 直接 alert 后端 API 异常,错误码



    很好的解决了请求是否成功已经逻辑是否成功的问题
    markgor
        143
    markgor  
       2019-10-22 12:00:04 +08:00
    @MakeHui #141 你別這樣說啊,我是墻頭草哪邊有理哪邊倒。

    畢竟一個人經驗和接觸到的知識面有點窄,所以理性的探討是支持的,沒任何敵意。
    你說出來,哪怕是我覺得錯的,但另一層面上我不是又了解多一樣東西嗎....
    當你說出來,我發現我是錯的,那我收穫更大了。
    frandy
        144
    frandy  
       2019-10-22 12:03:05 +08:00
    偏向于包一层,数据结构看起来舒服。

    个人项目->根据自己兴趣来。
    企业项目->根据历史问题来。
    新项目 ->根据协调沟通来。
    自己的经历总结出来一句话:一家公司的这种对外定义要统一,张三开发的项目接口包一层,李四不包层,如果直接暴露给前端,苦的是前端。否则后端还得弄个网关聚合,然后问题有回到了源头
    IamUNICODE
        145
    IamUNICODE  
       2019-10-22 12:06:47 +08:00
    做过这么多项目还没接触过没包的,除非是自己做着玩的,楼主威武
    Freeego
        146
    Freeego  
       2019-10-22 12:07:13 +08:00
    肯定要包啊,前端很多时候要用自定义的 code 做不同的逻辑处理。很多情况不是简单地打印一下错误信息就好了,除了系统错误还有各种业务逻辑异常呢,不用自己包的 code 怎么判断?
    ChristopherWu
        147
    ChristopherWu  
       2019-10-22 12:15:58 +08:00
    http 状态码可做简单判断,复杂的业务,还是需要的:
    你提供接口给客户端用,出错时,客户端想要详细而且够傻瓜的错误提示,难道你服务端整理好发给他嘛。
    肯定要靠两边约定统一的错误码,然后客户端根据此错误码自定义傻瓜报错给用户。
    Muninn
        148
    Muninn  
       2019-10-22 12:21:06 +08:00   ❤️ 2
    公司的按照公司的来

    自己的按照自己的喜好来

    想正规学大厂

    https://zhuanlan.zhihu.com/p/57367932

    我之前写过这个问题,我更支持 follow 国际大厂而不是国内的。
    back0893
        149
    back0893  
       2019-10-22 12:25:29 +08:00
    为啥不包?
    http code 我一般都是作为服务器的转眼
    code 作为具体的业务提示
    gtlions
        150
    gtlions  
       2019-10-22 12:35:44 +08:00 via iPhone
    太年轻了
    markgor
        151
    markgor  
       2019-10-22 12:36:29 +08:00
    結貼吧,
    設計源於生活,生活回歸設計。

    比方你去大保健。
    點了個 688 的套餐。
    工作人員給了你手牌 612
    然後 JS 來上鐘,
    打電話報鐘,
    如果輸入手牌號,系統返回“450Hz,-10±3dBm0,0.35s on/0.35s off”忙音,證明線路忙,JS 可能會過一兩分鐘再試。
    如果輸入手牌號,系統返回房間號,那麼 JS 只需要對一下房間號,看看有沒進錯房間即可。


    如果 JS 輸入手牌號後,系統無論線路原因或輸錯手牌號碼原因,均返回忙音,
    那 JS 太難了,
    除了要鍛煉嘴,聽力也要鍛煉,
    evilic
        152
    evilic  
       2019-10-22 12:37:05 +08:00
    @qlhai 是正解。

    还有,就是看实际使用吧。有些统一返回 http 200 的,但是调用者以实际的 code 字段做判断。因为有些调用者不一定能处理 http 状态码呀,要兼容……
    又或者调用者可能还有自己的处理逻辑需要记录下来,你返回一个 404,难道你不列出具体 404 的原因?

    code 要加的。
    binux
        153
    binux  
       2019-10-22 12:41:34 +08:00
    这一楼里面有一半的人都在跑题
    LZ 问的是成功时要不要包一层,你们扯什么异常?
    你们异常返回带不带 code 和成功的 data 有什么关系?
    你成功还要区分是什么姿势的吗?
    Hanggi
        154
    Hanggi  
       2019-10-22 12:42:31 +08:00
    举个简单的例子,一个 API:GET /foos/:fooId/bars/:barId/bazs/:bazId
    三个地方参数都检测,如果只返回 404 就很难知道哪个参数 not found。
    当然可以在 error message 里写 fooId not found,但是你就要去匹配一个字符串。
    而如果是 error code 1001, 1002, 1003 之类的,你就可以简单判断是哪一种 not found。

    关键还是业务逻辑吧,如果你能保证每个 API 都不会出现重复的 http 状态,那就不需要了,但是不太可能吧?
    adamzhuang
        155
    adamzhuang  
       2019-10-22 12:46:01 +08:00
    如果业务是严格按照 restful 把所有的东西都抽象成了资源,感觉 http 那一套 code 已经能够拟合大部分业务逻辑了,毕竟对资源的操作就只有 CRUD,感觉应该还是能够 cover 住。

    emmmmm,公司还是有包一层的,如果是自己项目的话,不太想加。
    HonoSV
        156
    HonoSV  
       2019-10-22 12:46:57 +08:00
    包一层,约定好 code 为 0 代表成功。如果 code 不是 0,那 msg 里就是对应的提示信息,前端可以直接展示给用户看
    h82258652
        157
    h82258652  
    OP
       2019-10-22 12:47:57 +08:00
    @IamUNICODE 现在不是包不包的问题,而是 200 例如 GET /person/1 这种返回包不包。现在整个帖子都变味了,全都在回复 error 的情况,返回 error 那毫无疑问需要 code。
    之前项目对接过微博、支付宝,200 都包了一层。
    但是看过 twitter 的 api,200 是不包的。
    adamzhuang
        158
    adamzhuang  
       2019-10-22 12:48:53 +08:00
    @Hanggi 我感觉这种情况下只需要弹个窗啥的?我觉得上面有一位老哥说的有点道理,错误码太多的话,前端错误处理分之就太多了。感觉非开放 API 的话,没必要到这样的粒度。
    evilic
        159
    evilic  
       2019-10-22 12:48:57 +08:00
    @binux

    LZ 哪里问“成功时”要不要包一层的? http 200 就是成功了?我 http 200 里面返回个 code 500,谁说它成功执行了?
    markgor
        160
    markgor  
       2019-10-22 12:50:01 +08:00
    @binux #153
    按你說法,失敗時候就包一層 code 在 response 裡,成功的話就把 code 從 response 裡刪除嗎?
    你這個說法,真的沒法接受哦。
    yamedie
        161
    yamedie  
       2019-10-22 12:51:31 +08:00
    @binux 反对你的观点, 顺便我也跑个题, 你个人简介里的菠菜网站怎么回事? 毕业设计还是真实的澳门赌场?
    lllllliu
        162
    lllllliu  
       2019-10-22 12:51:39 +08:00
    系统状态吗和业务状态码,业务状态码还有子业务状态码。
    我们一般在设计系统的时候就规划出一份业务状态码的文件了,根据业务到具体逻辑 一般是四位数,有几个全局的业务状态码,比如 1000 都是成功,1001 是什么错误之类的。。。。http 那个只能说有些时候会用到比如重定向啥的。。
    markgor
        163
    markgor  
       2019-10-22 12:52:44 +08:00   ❤️ 1
    @h82258652 #157
    那你這樣反而是脫褲子拉尿吧?

    失敗的話數據架構是包成這樣的:
    {
    code:xxx
    msg:'xxxx',
    data:'xxxxxx'
    }

    然後成功的時候,把 code 抽走,變成這樣了:
    {
    msg:'xxxx'
    data:'xxxx'
    }


    既然這樣你都想到了,那你還談什麼統一規格
    h82258652
        164
    h82258652  
    OP
       2019-10-22 12:53:29 +08:00
    @evilic 看我的跟帖回复,楼主我就是想表达 200 时包一层就是脱裤子放屁。可能顶楼没表达得很清楚,抱歉。
    h82258652
        165
    h82258652  
    OP
       2019-10-22 12:56:23 +08:00
    @markgor #163 我的意思成功的时候不是这样。
    例如 GET /person/1
    失败
    {
    "code": 400,
    "msg": "xxx",
    }
    成功
    {
    "id": 123,
    "name": "xxx"
    }

    你回复的,成功还是相当于包了一层。
    JounQin
        166
    JounQin  
       2019-10-22 12:58:06 +08:00 via iPhone
    有的公司是单纯不想 network 那里报错,全都是 200
    Rwing
        167
    Rwing  
       2019-10-22 13:00:06 +08:00
    @Muninn 支持
    markgor
        168
    markgor  
       2019-10-22 13:01:28 +08:00
    @h82258652 你這樣,我感覺更混亂.....
    另外,你帖子裡說的是:
    “但我觉得首先这 code 肯定是多余的,可以直接从 http 状态码里面读取。”
    那你失敗時候應該只有 http code 的 400,

    然後成功的時候,連 code 都沒有了,等於每個接口都要重複定義一個標準。

    那如果是請求成功(WEB HTTP 層的請求是正常的),業務處理是失敗的(查無用戶),
    那這個時候請問你是通過 response 返回 404 嗎?
    如果上了 CDN,設了 404 不死之身,那你的 code 最後不是又變成了 200 嗎?
    又或者如 LS 所說,如果你被運營商劫持了,4XX 和 5XX 的他們都重定向去他們自家的廣告,那 code 不是變成了 200 嗎?
    AlisaDestiny
        169
    AlisaDestiny  
       2019-10-22 13:03:17 +08:00
    我提一个问题你想想就有结论了。
    如果返回的 http status code 是 404,那前端到底应该认为是接口不存在还是要查询的数据不存在?
    markgor
        170
    markgor  
       2019-10-22 13:04:20 +08:00
    @h82258652 另外比較好奇,你們 nginx 都配置了 404 跳轉後全局錯誤頁後,返回都是 404 ?
    evilic
        171
    evilic  
       2019-10-22 13:04:44 +08:00
    @h82258652
    还是那句,看实际使用。
    有些统一返回 http 200 的(无论是否成功执行,根本不返回 404,301,500 的),因为有些调用者不一定或不想处理 http 状态码。
    例如我直接写个 html + js 调用,我根本不想处理 xhr.status,
    又或者我直接就写 sh 脚本 curl 了,本身一个简单的脚本就完成了,现在还要去处理 $http_code["201"],$http_code["202"],心累啊。

    人生苦短,我 python 去了。
    annielong
        172
    annielong  
       2019-10-22 13:05:02 +08:00
    这都是老生常谈了,状态少可以用 http 的 code,严谨一些还是自己定义 code
    morning
        173
    morning  
       2019-10-22 13:13:11 +08:00
    code 200 只是统一格式,错误响应也是这个格式,只是 code 不同,业务 code 可以快速定位问题减少重复劳动,建议在 http status 的基础上扩展,类似这种:
    40100001
    lack of appkey

    40100002
    sign invalid
    evilic
        174
    evilic  
       2019-10-22 13:14:43 +08:00
    @h82258652 是你没听懂大家的回复,http 200 在实际应用中不能很准确的表示成功。
    restful api 就是要让调用者爽。对于你提供的这种调用至少让我代码时不爽……我处理我的业务逻辑还觉得事儿多呢,哪里有时候再处理你的不同返回。
    m939594960
        175
    m939594960  
       2019-10-22 13:18:40 +08:00
    正确
    http status code:200
    body: {"id":1,"name":"qqq"}
    错误
    http status code: 403
    body: {"code":"403001","message":"用户名火密码错误"}
    littleshy
        176
    littleshy  
       2019-10-22 13:24:05 +08:00
    200 不包。错误则返回 400 以上状态码及统一格式的错误信息,如果想要你可以在信息加错误码。
    evilic
        177
    evilic  
       2019-10-22 13:24:49 +08:00
    ```
    code = 200
    msg = 'success'
    try:
    data = service.do_something(a, b, c)
    except Exception as e:
    code = e.code
    msg = str(e)
    self.write({'code': code, 'msg': msg, 'data': data})
    ```

    上面这是示例代码,不是真实代码。
    我觉得这个是正常代码的写法,不是你说的额外包一层呀。反倒你说的,我觉得是需要额外的去一层。

    ```
    if code == 200:
    result.pop('code')
    ```
    你的代码应该多了 2 行才对呀……
    IamUNICODE
        178
    IamUNICODE  
       2019-10-22 13:29:06 +08:00
    @h82258652 你这样直接返回数据当然可以,但是为什么能统一返回格式不统一?手机端强类型的话要多做一层判空,他们当然不会愿意,这个东西后端直接封装一下返回,又不是什么难事。
    l00t
        179
    l00t  
       2019-10-22 13:35:23 +08:00
    @index90 #116 那我要处理呢?该处理的数量一个都不会少,反而原本一个 int 等于的判断,要变成字符串匹配?
    nvkou
        180
    nvkou  
       2019-10-22 13:41:35 +08:00 via Android
    @AlisaDestiny 按照规范,你可以 options 一下确定服务状态。另外,有错误消息的 404 和纯 404 也不一样啊
    BloodyZealot
        181
    BloodyZealot  
       2019-10-22 13:44:30 +08:00
    国内响应外面包一层的情况居多,所以你听到的反对声音多。项目上统一标准就行了,至于是不是在用标准的 Rest 风格并不是很重要,没必要互相杠...
    binux
        182
    binux  
       2019-10-22 14:08:48 +08:00
    @evilic #158 你话都读不懂的话就不要回了,你自己问 LZ 是不是问成功时要不要包一层
    @markgor #159 是的,怎么了? github, twitter, google API 成功都是直接返回对应 object 的。没有 code 你就不会判断成功了吗?
    @yamedie #160 你自己网络被劫持都不知道,还是别出来说话了吧
    Narcissu5
        183
    Narcissu5  
       2019-10-22 14:09:46 +08:00 via Android
    @AlisaDestiny 204 no content 了解一下
    yamedie
        184
    yamedie  
       2019-10-22 14:11:53 +08:00
    @binux 俩网站都被墙,估计没做什么好事吧
    starsli
        185
    starsli  
       2019-10-22 14:13:00 +08:00
    可以结合使用。
    成功请求返回 200,不用对结果再包一层。
    业务错误或代码错误返回 4xx、5xx,后台统一捕获,返回一个同一的异常对象,可以包括错误码、描述、调试等信息。
    前台使用也比较简单,就像下面这样:
    ```
    axios.get('/user?ID=12345')
    .then(function (response) {
    // 200
    // 正常业务处理
    })
    .catch(function (error) {
    // 4xx、5xx
    // 异常处理
    });
    ```
    assad
        186
    assad  
       2019-10-22 14:14:19 +08:00
    感觉大家都很闲啊,一个这个问题不亦乐乎。一句话,多好快省解决问题。标准,何为标准,都是人定的。看来还是年轻!
    Narcissu5
        187
    Narcissu5  
       2019-10-22 14:15:27 +08:00 via Android
    一般来说 404 错误在开发测试环境就应该消灭掉,到了正式环境才发现 url 拼错了有什么意义。你的 js 还能自己修复么?有的人啊工作经验可能是有了,就是不会总结
    Ianchen
        188
    Ianchen  
       2019-10-22 14:16:33 +08:00
    @yamedie 是的, 我不是前端. 我反驳的是 70xx 这种错误码无意义, 后面你的 9001 代码就有存在的必要, 因为前端需要根据这个固定代码来跳转到登录页面引导用户登录. 我的逻辑很简单, 前端需要根据返回的错误码来进行页面上的逻辑处理, 则规定一个具体代码, 如果没有逻辑处理, 定义那么多错误代码我是觉得没意义.

    想一想, 验证码失效, 一个提示语告诉用户即可, 无需定义 7001 这种代码, 验证码校验失败也是一个提示语的事情, 7002 的代码无存在意义. 除非你们的产品经理有要求你们在有这种提示语时有特殊的界面交互动作, 那这 7002 的代码就有其存在的意义, 前端需要知道这个错误码, 才能做逻辑处理交互.
    xingheng
        189
    xingheng  
       2019-10-22 14:20:48 +08:00
    @helone 客户端有时候需要基于后台不同的 code 来实现不同的页面跳转等等特定需求
    yamedie
        190
    yamedie  
       2019-10-22 14:21:16 +08:00
    @Ianchen 所以说, 如果今天 PM 在设计评审时没提到某个 case 需要页面做逻辑处理, 改天 PM 脑洞大开提出这样那样的需求, 你能因为接口没有返回 code 判断不到而拒接这个需求吗?
    xingheng
        191
    xingheng  
       2019-10-22 14:26:40 +08:00
    @Narcissu5 如果客户端要实现 code=9001 的时候立刻弹出登录页重新登录呢?这种逻辑绝对不止 1%
    markgor
        192
    markgor  
       2019-10-22 14:28:37 +08:00   ❤️ 1
    @binux
    https://developers.google.cn/pay/api/web/reference/response-objects#example_6
    要不你看看 googlepay api ?
    google 某些接口成功不會返回,但某些接口成功會返回,這你又怎麼看?

    没有 code 你就不会判断成功了吗?
    可以判斷成功啊,但你怎麼區分網絡請求成功和業務請求成功?
    哦,對了,你肯定又要繞回去題主說的是成功而不是失敗。
    但是你可以也看清楚下,題主後面的字句嗎?
    "但后面有自己项目的话,还是想弄标准一点。不知道一般来说,大家是怎样实现?"
    你覺得實際項目中真有只需要考慮成功而不需要考慮失敗的設計嗎?


    另外我不明白,你是有多少項目對接的 google,github,twitter ?還是你的項目全都是對接這些?
    如果你平時實際對接的“第三方”比較多,你就自然明白為什麼那麼多人說要包多個 code。


    另外,阿里,騰訊,百度這三家 bat 也是進不了你法眼吧?怎麼你舉例只是 google,github,twitter,國內現況不看看?
    崇洋媚外 也要有個度,什麼樣的設計歸根到底不是應該要貼合市場業務嗎?
    Ianchen
        193
    Ianchen  
       2019-10-22 14:28:50 +08:00
    @yamedie 你也说是因为 PM 后面脑洞大开时提出的, 与你当时写完后不给 code 并不冲突, 因为这是后面提出的改进. 并且 PM 提出这个需求, 你以评审是否有必要, 有则给开发新加个这种工作量需求, 没有那就驳回这个需求即可, 不是吗?
    xingheng
        194
    xingheng  
       2019-10-22 14:32:08 +08:00
    @baiyi

    {"data":null}这种数据在前后端都有框架可以实现过滤;
    现在主流的 iOS 数据序列化框架都可以区分{}和[],你是不是被你们 iOS 客户端开发忽悠了
    AyanamiRei
        195
    AyanamiRei  
       2019-10-22 14:34:44 +08:00
    {
    "code": 2,
    "msg": "删除失败",
    "data": []
    }

    我们还强调 data 必须是数组格式的括号
    xuanbg
        196
    xuanbg  
       2019-10-22 14:37:45 +08:00
    @leopardwei 正常情况下 http 永远是 200,根本不需要管。如果 http stats 不是 200,那就是网络或者服务器本身出问题而非数据 /业务逻辑的问题。
    yamedie
        197
    yamedie  
       2019-10-22 14:38:31 +08:00
    @Ianchen 我觉得写易维护可扩展的代码最直接的目的就是为了提早下班, 如果 pm 提了一个在用户交互角度看来合理的需求, 而接口出参不支持, 需要重新修改出参报文格式, 前后端加班联调, 得不偿失吧. 针对每个业务场景的特殊错误增加一个错误码, 是低成本高收益的一件事, 为何这么多人反对, 还有要求 200 时直接返 data, 错误时才包一层的, 搞双重标准, 这样合理吗, 感觉很低效吧?
    binux
        198
    binux  
       2019-10-22 14:39:20 +08:00
    @markgor #191 什么怎么看? googlepay 很明显就是我说的成功直接返回 object 啊,即使是很简单的 { "result": true }
    业务请求成功 body 会有内容啊,为什么要区分网络请求成功,然后业务请求失败?你拿不到预期的内容那就是失败。
    失败就去解析失败 object 就好了啊,你自己的例子已经给你示范了,你无法理解吗?

    bat 自己连个全站 HTTPS 都做不到,他们的规范你还要去学?
    再者我供职的公司压根就没有面向中国市场的业务啊。
    Joyboo
        199
    Joyboo  
       2019-10-22 14:40:50 +08:00
    那么多开源接口{code:0,data:[],msg:""}这种格式不是没有道理的,不要想当然
    markgor
        200
    markgor  
       2019-10-22 14:46:23 +08:00
    googlepay 很明显就是我说的成功直接返回 object
    上面哪個人說的不是返回 object,上面都是在討論返回的 object 是否需要包含成功代碼,還是說直接通過 http 的 200 表示成功。建議你話 1-2 分鐘看看上面針輪的話題和 LZ 的提問。

    “业务请求成功 body 会有内容啊,为什么要区分网络请求成功,然后业务请求失败?你拿不到预期的内容那就是失败。

    失敗時候的處理方式不一樣,
    最簡單的例子,網絡失敗隔 10 分鐘重試,業務失敗檢查自身提交業務數據。如果業務失敗也是按網絡失敗處理,那你不就等於叫別人 ddos 你嗎?

    “失败就去解析失败 object 就好了啊,你自己的例子已经给你示范了,你无法理解吗?”
    建議你話 1-2 分鐘看看上面針輪的話題和 LZ 的提問。

    “bat 自己连个全站 HTTPS 都做不到,他们的规范你还要去学?”
    總有人覺得自己比 bat 都厲害,但卻幹不掉 bat。

    “再者我供职的公司压根就没有面向中国市场的业务啊。”
    那我沒什麼好說的了。
    1  2  3  4  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3268 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 12:59 · PVG 20:59 · LAX 04:59 · JFK 07:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.