V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
watanuki
V2EX  ›  程序员

为什么后端开发都喜欢自己定义 responseCode? HTTP 状态码不够用吗?

  •  
  •   watanuki · 2020-05-29 14:10:45 +08:00 · 26408 次点击
    这是一个创建于 1669 天前的主题,其中的信息可能已经有所发展或是发生改变。

    所有请求都返回 200,然后自己定义 responseCode, 好像很多大厂的后端接口都是在这样做的,这样做有什么好处? 现在后端开发是不是已经有了关于 responseCode 的统一标准?还是一个公司一套标准? 如果没有统一标准,大家在开发个人的后端项目时也会用 responseCode 吗?

    216 条回复    2024-01-04 19:45:36 +08:00
    1  2  3  
    pushback
        101
    pushback  
       2020-05-29 18:30:34 +08:00
    我的开发习惯是要处理参数错误 http 那边响应 400 没问题,但是才 responseCode 这里我会返回 400.01~400.99 来标明参数错误的原因
    no1xsyzy
        102
    no1xsyzy  
       2020-05-29 18:33:55 +08:00
    @Vegetable #62 前端处理业务逻辑本身,而不需要再研究 404 究竟是 URL 拼错了还是没有这个对象。
    这句话我同意,但问题在于,没有这个对象难道不应该是 400 ? null 对象不能进行 GET 操作(开个玩笑)

    其实你想象中的很多问题,大部分都应该让自动化测试和配置反哺解决的,就比如 URL 拼错问题,RESTful 中提到,API 返回另一个内容时应当采用 URL 而不是 id 。比如 users?{query} 应当得到的是形如 ["/users/alice", "/users/bob"],而每一个用户的 URL 则应由路由生成,比如 Flask 有 url_for,错也错得一致,反而没什么问题,Don't Repeat Yourself 。
    再不济也是由 CI 和 unit test 捕获。
    如果这层都漏了漏到用户侧去了,返回 404 还是返回 400 都没什么差别。我远在接受编程相关知识之前就长期各种折腾极限情况,发生这种情况我只能意识到 “我对此无能为力”,用户侧拿到的信息再多也等于没有。如果已经是你自己跑测试了,那就不存在 trace 能解决而 debugger 不能解决的问题。
    colorfulberry
        103
    colorfulberry  
       2020-05-29 18:43:06 +08:00
    用户看到的所有错误都是网络错误哈哈哈。
    no1xsyzy
        104
    no1xsyzy  
       2020-05-29 18:46:24 +08:00
    @sunny352787 #90 我看我没有人身攻击,如果你觉得有哪句让你觉得被冒犯了还请指出(让我见识见识你有多玻璃心
    至于你,“就这智商讨论个屁” 这是不是人身攻击呢?我且当它不是,以保持与您继续讨论的氛围。
    一来,有一个算一个,认认真真用 “智商” 这个词的,不是坏就是蠢。如果你不知道的话,我且当您犯了一点点正常人都会犯的小蠢;不过我想指出,“智商” 一词是焦虑营销中生搬硬套的概念,原本为了研究青少年大脑发育而发明这个词的那个人都受不了,在 Medium 上发文章指出了这点( https://medium.com/incerto/iq-is-largely-a-pseudoscientific-swindle-f131c101ba39 )。
    至于 “不得已而为之的解决方案”,我疑惑您的中文、英文和工科都是谁教的?“不得已而为之” 的不叫 “解决方案”,这仨学科里都应该讲过。
    Varobjs
        105
    Varobjs  
       2020-05-29 18:48:59 +08:00 via Android
    月经贴了
    freakxx
        106
    freakxx  
       2020-05-29 18:49:52 +08:00
    这个问题在 V 站讨论挺多次了,

    说实话,感觉偏颇说一句,挺丑的。

    http code 按实际情况返回
    业务需要,在 response 里面再做一层 response code 区分场景
    RRRoger
        107
    RRRoger  
       2020-05-29 18:52:13 +08:00
    @blessyou #96 原文:“不同模块的错误码分成 100xxx , 200xxx, 300xxx 比较好排查”
    ======
    回复:+1 这个没毛病
    no1xsyzy
        108
    no1xsyzy  
       2020-05-29 19:13:22 +08:00   ❤️ 2
    HTTP 为什么要状态码?这是为了标记 “续延”,是为了能够让客户端正确地应对这一值而作出不同的响应的。
    比如,为什么要返回 3xx ?是为了能够让客户端知道,接下来需要根据 Location 头进行跳转了。
    为什么要返回 1xx ?是为了让客户端知道发生了一些协议层面上的 meta 改变。
    为什么要返回 4xx 和 5xx ?是为了让浏览器正确地理解异常状态的发生,并据此进行恰当的重试,或者不应重试。
    总体上来说,逻辑上大致是这样:

    what_then = continuation_vector[response.status_code]
    what_then(response)

    它几乎等价于回调函数的偏移量。

    而无论业务码还是扩展 HTTP 状态码都是没必要的,就 HTTP 那些足够了,大部分 CRUD 项目甚至只需要三个,一个 404 一个 200 一个 302,也就有些情况需要个 101,但多半不是我手写的 101 。
    第一,现在的 UI,能够在发送请求前对数据作大部分验证。诸如 “这一字段必须是字符串表示的 decimal” 这种提示你一个应用从上线到废弃都不一定会显示一次,因为前端在发送请求前应当进行了验证,而后端在验证不通过时直接报错即可,不需要任何提示。
    第二,大部分业务错误发生时「客户端(不包括用户)没有任何处理办法」,这时候决定续延的不是机器而是人,码自然不如文字提示,简单地将错误消息发到 UI 上去即可。
    以上两种情况,应当覆盖 90% 的业务场景,以及 99.9(99)% 的实际 HTTP 请求。
    不能满足的有二:一、你在开发一个放给外部开发者使用的 API ;二、你在造一个奇美拉。
    no1xsyzy
        109
    no1xsyzy  
       2020-05-29 19:23:27 +08:00   ❤️ 1
    @no1xsyzy #108
    说明一下,奇美拉的意思是缝合怪,也包括了所有微服务架构。
    重点在于,奇美拉系统的重点在于各个部分是 “有机” 地结合的,任何一比特的信息(将来)都可能是有用的,那自然要从开头就写得容易被提取。不过建议用字符串当符号使,比数字好千倍。
    {"result": 200, "data": ...} 和 {"result": "OK", "data": ...} 你想看哪个?

    我觉得足以终结一切此类主题了。
    xingheng
        110
    xingheng  
       2020-05-29 19:27:06 +08:00
    status code 和 response code 对我而言我能接受的,但是我写客户端的时候,在客户端会把这两个 code 映射成一个 int code,所以想问一下后端开发,现在 100<= http status code <600,那你们业务层的 code 一般是定义在哪个区间?
    Leigg
        111
    Leigg  
       2020-05-29 19:27:38 +08:00 via Android
    虚心一点,多学习
    myCupOfTea
        112
    myCupOfTea  
       2020-05-29 19:50:25 +08:00   ❤️ 2
    @cheng6563 按照 restful 有啥招镣铐的,jira 算复杂吗,aws 算复杂吗
    这边附上一个 jira 的 rest api 文档
    https://docs.atlassian.com/software/jira/docs/api/REST/8.8.1/#api/2/issue-createIssue
    xiangwan
        113
    xiangwan  
       2020-05-29 19:56:40 +08:00
    @no1xsyzy 同学在#47 的焦点貌似是想操练下刚学到的定律。 @fatedier @Vegetable

    随便搜了阿里云的错误代码,@no1xsyzy

    例 1:

    错误代码 Http 状态码 Message 描述
    I400HD 400 Invalid Header ${HeaderName} ${Reason} HTTP 请求头非法
    I400MH 400 Header ${HeaderName} is Required 缺少 HTTP 请求头
    I400BD 400 Invalid Body: ${Reason} HTTP 请求包体非法
    I400PA 400 Invalid Request Path ${Reason} HTTP 请求路径非法
    I405UM 405 Unsupported Method ${Reason} 不支持的 HTTP 请求方法

    例 2:

    20 OK HSF 调用成功
    30 client timeout 调用端超时
    31 server timeout 服务端超时
    40 bad request 请求不合法
    50 bad response 返回结果不合法
    60 service not found 服务没有找到
    70 service error 服务错误
    no1xsyzy
        114
    no1xsyzy  
       2020-05-29 20:03:03 +08:00
    @xiangwan #113 精准符合例外一✔
    no1xsyzy
        115
    no1xsyzy  
       2020-05-29 20:14:37 +08:00
    @xiangwan #113 啊,不过休谟剃刀也算是刚学到吧,如果之前的话我会说珍珠效应的。
    ihipop
        116
    ihipop  
       2020-05-29 20:23:15 +08:00 via Android
    @littleylv http 422
    xiangwan
        117
    xiangwan  
       2020-05-29 20:28:51 +08:00
    @no1xsyzy
    我没办法反驳你的 #113
    本来想先反驳第二点,写完后发现,开头写的是“大部分。。。“
    然后再去看你说的第一点,描述的也是“大部分”状况
    而且你还列了两个例外。

    你的观点大部分时候是对的,另外的时候是错误的。
    cabing
        118
    cabing  
       2020-05-29 20:35:15 +08:00
    状态码不够多。
    szyp
        119
    szyp  
       2020-05-29 20:40:53 +08:00 via iPhone
    @littleylv 我司的参数检验返回的都是 400
    no1xsyzy
        120
    no1xsyzy  
       2020-05-29 20:51:55 +08:00
    @xiangwan 我的上面几个 “大部分” 都带兜底例外情况,“大部分”+“例外” 合起来估计超过 5 个 9 吧,并且例外还指明得挺精确的。
    这就是像是 “重启解决 90% 的问题,重装解决 99% 的问题,重买解决 99.99% 的问题,其他问题不存在解决的办法”。

    不过两个例外要重构一下:第一个例外是你不能或者不希望被调试,比如这一系统的持续运行非常关键,或者 API 的实际使用方是外部单位;第二的例外是整个系统活动部件非常多,做到有机结合,高聚低耦,并且每个部分常常单独变动。这两个例外实际上具有一体两面性:第一例外中把所有外部单位集合起来视作系统的一部分,就变成了第二例外;反之亦然。

    但同时,我也要指出,这两种例外,真的碰上的情况实在太低,加起来,按场景流程计不足 10%,按实际 HTTP 请求数计不足千分之一,两种例外兜不住的情况低于十万分之一。如果谁觉得自己是十万里挑一的天选之人也欢迎讲故事。

    至于我已经明确指出了例外的情形、发生的条件、构成例外的原理,你要觉得这也能算车轱辘话那我没话说。
    xiangwan
        121
    xiangwan  
       2020-05-29 21:10:01 +08:00
    @no1xsyzy
    我反驳的是:业务码没用论。
    你 5 个 9 也没到 100%,很容易打到其他部分。

    错误码就算前端处理不了,显示出来也是有用的,用户把错误码反馈回来后有助于 debug
    sanggao
        122
    sanggao  
       2020-05-29 21:12:54 +08:00   ❤️ 2
    感觉前端小丑就是挺多的,喜欢折腾,又肤浅。像极了文科生
    no1xsyzy
        123
    no1xsyzy  
       2020-05-29 21:29:37 +08:00
    @xiangwan #121 “其他问题不存在解决的办法”,至少已经不是返回个 code 能解决的了,大概需要把 Exception 带 traceback 给序列化了。
    这种情况应该后端打 error 而不是漏到前端去。遗憾的是,现在似乎不存在哪个 Web App 框架会在报错时将整个运行过程抓取供复盘的,我也没听说过哪个语言的哪个实现能做到这一点,不然那才是正确做法,近乎调试的复盘。
    cedoo22
        124
    cedoo22  
       2020-05-29 21:38:42 +08:00
    一般错误用 http code, 业务相关错误用自定义 code. 但是一般代码不规范就喜欢一股脑全整成自定义错误。丑陋无比!
    xiangwan
        125
    xiangwan  
       2020-05-29 21:44:48 +08:00
    @no1xsyzy 没有说可以*解决*问题,是可以*辅助*解决问题 ,
    看下这个场景:错误码 site:https://answers.microsoft.com

    “将整个运行过程抓取” ,如果是分布式的怎么办?
    现有方案是记录带 request id 的日志
    leo108
        126
    leo108  
       2020-05-29 21:48:17 +08:00   ❤️ 1
    @kkkwar #92 你是不是以为除了 200 状态码之外其他的状态码就只能返回 Header 而不能返回 Body ?
    angryfish
        127
    angryfish  
       2020-05-29 21:50:19 +08:00 via iPhone
    我为啥要按 restful 来,不喜欢那玩意
    billtsui
        128
    billtsui  
       2020-05-29 21:50:41 +08:00
    不够用,自定义状态码用来返回业务相关的信息。拿注册功能来说,你用 http status code 怎么表示当前账户已存在?
    holinhot
        129
    holinhot  
       2020-05-29 21:54:41 +08:00
    没有 responseCode 请问如何跟踪到返回错误的具体执行模块块和代码行
    no1xsyzy
        130
    no1xsyzy  
       2020-05-29 21:57:34 +08:00
    @xiangwan #125 啊操作系统问题得用户自己动手解决,虽然操作流程很明确但确实不便直接提示,而采用知识库或者 wiki 的形式贴出解决办法…… 不过是不是贴 wiki 的 URL 会更好?虽然加强了耦合性。
    确实比 pacman 出问题每次拿着错误提示去搜索要明确……

    不过讨论范畴在 Web API 不是么……

    是,目前的方案基本止步于此了,没打 log 的变量是看不到的。或者可能说我其实想要的是一个赋值即打 DEBUG log 带序列化的设施……
    nvkou
        131
    nvkou  
       2020-05-29 22:02:15 +08:00 via Android
    @muzuiget 发个 options 不就知道接口挂没有了?这种问题老早就解决了
    no1xsyzy
        132
    no1xsyzy  
       2020-05-29 22:02:48 +08:00
    @billtsui #128 我于 #108 指出
    > 第二,大部分业务错误发生时「客户端(不包括用户)没有任何处理办法」
    不需要特地表示当前账户已存在,只需要向前端提示操作失败,给个 404,msg 报 “用户已存在” 就行了。

    如果想浪漫点可以 409 Conflict
    SilencerL
        133
    SilencerL  
       2020-05-29 22:10:24 +08:00
    可是就算 HttpStatus 返回非 200 的时候也可以往 Response 里面塞东西啊...
    比如我 HttpStatus 返回 502, Response 里面定义好返回的 message 写原因, 那么没有 message 的就不是业务返回的 502, 而是网关 /CDN/代理等等其他外部原因造成的.
    nvkou
        134
    nvkou  
       2020-05-29 22:26:47 +08:00 via Android
    这标准出来这么久了,还觉得码不够用难道不是业务设计的粒度问题?
    网络传输过程中的错误该不该捕获?网关超时和服务器超时该不该一视同仁?
    路由器运营商劫持不就是惯的吗?
    HTTP 各种客户端能不能方便的过滤状态码?还是要重复造轮子?
    HTTP 各种服务器能不能方便的作日志统计服务质量?还是要保留所有请求原文?
    securityCoding
        135
    securityCoding  
       2020-05-29 22:55:00 +08:00
    麻烦上面说可以用的多写写代码 , 不要误导人
    lllvvv
        136
    lllvvv  
       2020-05-29 23:00:20 +08:00 via Android
    swim2sun
        137
    swim2sun  
       2020-05-29 23:11:57 +08:00
    这帖子让我认识到“国内主流”跟“国际主流” 差别是真的大
    skydrive
        138
    skydrive  
       2020-05-29 23:15:11 +08:00
    @securityCoding 入行四五年就可以倚老卖老了?你怎么知道人家代码写得比你少?
    cedoo22
        139
    cedoo22  
       2020-05-29 23:26:53 +08:00
    @leo108 422 实体 语法正确,所包含指令无法处理。 字段确实 属于语法错误。
    weixiangzhe
        140
    weixiangzhe  
       2020-05-29 23:27:32 +08:00
    以前端角度来说一下,赞成用 http 状态码加 500 错误内自定义 response 里加业务 code 的形式
    1. post get delete 本身没有什么区别,但是可以大大方便调式
    2. 自定义业务代码当然需要,但是状态码一并处理可以大大的加快前端定位问题的速度, 401 403 和通用错误的 500,在调试工具下一眼就看到了,都是 200 的话需要一个一个点过去看,非常耗时
    3. 在非 200 下 response 也能自定义,和你们 200 加 code 区别只是在于状态码不同,当前前端的大部分 ajax 类的库在非 200 时都默认配置了错误捕获,易于前端的通用错误处理
    4. 在 200 时有错误 若要配置全局的错误捕获的话的,需要额外配置,又由于每个项目错误的标准不同,自定的 message 之类的位置也不同,每次都要做一次封装处理比较麻烦,又加之在调试面板里不会抛红,调试体验不佳
    5. 常用的状态码我看项目里也就 200 400 401 403 404 405 500 502 301 302 之类的加一加心智负担也不重,不确定的码 500 就好, 非错误类型放 200 内加 code 当然也可以
    securityCoding
        141
    securityCoding  
       2020-05-29 23:30:44 +08:00
    @skydrive 那你继续用
    zouzou
        142
    zouzou  
       2020-05-29 23:43:48 +08:00
    1.http status 统一 200,code 在 http response body 中定义;
    2.使用不同的 http status,也有自定义的 response code 。
    两种方式各有应用场景,第一种多在单体应用中,前后端协商好怎么处理 http body ;
    第二种多在微服务中,api gate 转发 http 请求,有监控系统需要统计请求的相应结果,使用 http status 来表示处理状态。
    leon0903
        143
    leon0903  
       2020-05-29 23:44:49 +08:00
    我就想问一句,那些说能用 http status code 的, 你们真的在有一定规模的真实项目中用了么?
    ArtIsPatrick
        144
    ArtIsPatrick  
       2020-05-30 00:31:06 +08:00 via iPhone
    谁和你都返回 200 了,http 状态该返回啥返回啥。比如接口发生异常了,http code 肯定应该是 500,如果换成你自己定义的 code 浏览器是不会识别的。这并不符合 http 协议的规范。
    ArtIsPatrick
        145
    ArtIsPatrick  
       2020-05-30 00:32:55 +08:00 via iPhone
    @guyeu 谁和你都返回 200 了,http 状态该返回啥返回啥。比如接口发生异常了,http code 肯定应该是 500,如果换成你自己定义的 code 浏览器是不会识别的。这并不符合 http 协议的规范。
    saberlong
        146
    saberlong  
       2020-05-30 00:44:11 +08:00 via Android
    1.写的服务都是部署在内部由你控制。但是由网关或者代理服务出去时不受你管理。你是无法控制他们的处理策略。nginx 默认样例就有对 50x 使用 50x.html 返回。多个团队合作时,会划分错误码。如果使用 httpstatuscode,无法应对团队扩展和业务扩展。
    2.服务通信往往不是单单 http 协议。写一个接口,内部框架会转成各种内部 rpc 协议。http 协议进行通信仅仅只是一种。http 的 statuscode 可不是唯一标准。
    binux
        147
    binux  
       2020-05-30 00:47:34 +08:00 via Android
    @ArtIsPatrick #135 随便你返回什么 code,只要是三位数字就可以,浏览器根本就不要求识别未定义的 code,但是 app 可以自行处理。
    cz5424
        148
    cz5424  
       2020-05-30 00:52:03 +08:00
    @no1xsyzy 如果是密码错误,需要弹出找回密码框,用相同的错误码,前端用字符串判断吗?
    ArtIsPatrick
        149
    ArtIsPatrick  
       2020-05-30 00:56:39 +08:00 via iPhone
    @binux 是的,然而你返回的是一个别人都没见过的 http code 这有利于对接和排查问题吗?之所以尽量使用 http 协议规定的 http 码是因为这是行业公认的,大家都能够理解。可以快速排查问题。
    ArtIsPatrick
        150
    ArtIsPatrick  
       2020-05-30 01:00:34 +08:00 via iPhone
    @binux 我之所以说浏览器的识别问题,因为能更直观的排查错误,比如在 chrome 的控制台,400 和 500 的错误是会显示成红色的,300 是黄色的。
    SpencerCJH
        151
    SpencerCJH  
       2020-05-30 01:04:22 +08:00   ❤️ 1
    @leon0903 我公司组里这边的项目都是用 HTTP Code 的。因为 Google Api Design 里规定好了用什么 code 。错误消息的格式都是固定的:

    {
    "error": {
    "code": 401,
    "message": "Request had invalid credentials.",
    "status": "UNAUTHENTICATED",
    "details": [{
    "@type": "type.googleapis.com/google.rpc.RetryInfo",
    ...
    }]
    }
    }

    具体参考: https://cloud.google.com/apis/design/errors

    HTTP RPC 说明
    200 OK 无错误。
    400 INVALID_ARGUMENT 客户端指定了无效参数。如需了解详情,请查看错误消息和错误详细信息。
    400 FAILED_PRECONDITION 请求无法在当前系统状态下执行,例如删除非空目录。
    400 OUT_OF_RANGE 客户端指定了无效范围。
    401 UNAUTHENTICATED 由于 OAuth 令牌丢失、无效或过期,请求未通过身份验证。
    403 PERMISSION_DENIED 客户端权限不足。可能的原因包括 OAuth 令牌的覆盖范围不正确、客户端没有权限或者尚未为客户端项目启用 API 。
    404 NOT_FOUND 找不到指定的资源,或者请求由于未公开的原因(例如白名单)而被拒绝。
    409 ABORTED 并发冲突,例如读取 /修改 /写入冲突。
    409 ALREADY_EXISTS 客户端尝试创建的资源已存在。
    429 RESOURCE_EXHAUSTED 资源配额不足或达到速率限制。如需了解详情,客户端应该查找 google.rpc.QuotaFailure 错误详细信息。
    499 CANCELLED 请求被客户端取消。
    500 DATA_LOSS 出现不可恢复的数据丢失或数据损坏。客户端应该向用户报告错误。
    500 UNKNOWN 出现未知的服务器错误。通常是服务器错误。
    500 INTERNAL 出现内部服务器错误。通常是服务器错误。
    501 NOT_IMPLEMENTED API 方法未通过服务器实现。
    503 UNAVAILABLE 服务不可用。通常是服务器已关闭。
    504 DEADLINE_EXCEEDED 超出请求时限。仅当调用者设置的时限比方法的默认时限短(即请求的时限不足以让服务器处理请求)并且请求未在时限范围内完成时,才会发生这种情况。

    例子
    HTTP RPC 错误消息示例
    400 INVALID_ARGUMENT 请求字段 x.y.z 是 xxx,预期为 [yyy, zzz] 内的一个。
    400 FAILED_PRECONDITION 资源 xxx 是非空目录,因此无法删除。
    400 OUT_OF_RANGE 参数“age”超出范围 [0,125]。
    401 UNAUTHENTICATED 身份验证凭据无效。
    403 PERMISSION_DENIED 使用权限“xxx”处理文件“yyy”被拒绝。
    404 NOT_FOUND 找不到资源“xxx”。
    409 ABORTED 无法锁定资源“xxx”。
    409 ALREADY_EXISTS 资源“xxx”已经存在。
    429 RESOURCE_EXHAUSTED 超出配额限制“xxx”。
    499 CANCELLED 请求被客户端取消。
    500 DATA_LOSS 请参阅备注。
    500 UNKNOWN 请参阅备注。
    500 INTERNAL 请参阅备注。
    501 NOT_IMPLEMENTED 方法“xxx”未实现。
    503 UNAVAILABLE 请参阅备注。
    504 DEADLINE_EXCEEDED 请参阅备注。

    以登录和注册为例,用户已经存在(名字,id 重复什么的)就是 409 ALREADY_EXISTS ;密码错误是 401 UNAUTHENTICATED ;找不到这个用户是 404 NOT_FOUND ;
    SpencerCJH
        152
    SpencerCJH  
       2020-05-30 01:06:06 +08:00
    软件开发当然是自由的,想怎么搞就可以怎么搞,没有最好的方案与设计,大家对软件工程有追求的话还是看看国外大厂是怎么做的。
    binux
        153
    binux  
       2020-05-30 01:07:04 +08:00
    ArtIsPatrick
        154
    ArtIsPatrick  
       2020-05-30 01:08:40 +08:00 via iPhone
    @binux 没什么不可以,放 body 里更好,code 加 message 。
    SpencerCJH
        155
    SpencerCJH  
       2020-05-30 01:10:10 +08:00
    哎我真的是傻逼来回这个月经贴。。。
    no1xsyzy
        156
    no1xsyzy  
       2020-05-30 01:13:46 +08:00
    @cz5424 #148 能别提这种经典且彻底的设计失误了吗……
    302,Location 带找回密码的地址,再由 JavaScript 作为路由捕获,甚至没了 JavaScript 也能正常运行,符合 PE 。
    gadsavesme
        157
    gadsavesme  
       2020-05-30 02:30:38 +08:00
    协议归协议,业务数据归业务数据,非要合在一起也是无语。快递送到就得了,非得关心我包裹里面是啥东西干嘛?
    laike9m
        158
    laike9m  
       2020-05-30 03:23:20 +08:00 via Android
    谁让你们用 JSON 而不用 protobuf 呢🤷
    nuk
        159
    nuk  
       2020-05-30 04:10:38 +08:00
    怕通过代理上网的被劫持 404 的客户气的跳起来骂娘
    touno
        160
    touno  
       2020-05-30 04:16:11 +08:00
    不写 BUG 对不起自己~哈哈哈哈哈
    cs419
        161
    cs419  
       2020-05-30 07:01:42 +08:00
    小孩子才做选择题
    lscho
        162
    lscho  
       2020-05-30 11:01:01 +08:00
    @no1xsyzy #132 是认真的吗?你这样不还得判断字符串吗? 404 不只是后端会给你,路由器、运营商、设备都有可能给你,不做判断了吗?
    mikicomo
        163
    mikicomo  
       2020-05-30 11:01:03 +08:00
    我们同时保留了 httpcode 和 errerCode

    httpcode 400
    errorCode 40010100 规则:{httpcode}{业务 code}{错误 code}
    sayitagain
        164
    sayitagain  
       2020-05-30 11:14:19 +08:00
    @jzmws 哈哈哈,我司返回格式和你惊人的一致,不过我们是 code=1 表示成功
    LichMscy
        165
    LichMscy  
       2020-05-30 11:54:14 +08:00
    因为我们会对项目的接口统计 SLA,平台今年的 KPI 要求五个 9 的可用率,出现 4xx5xx 就会影响,所以所有的请求都 2xx 了。
    yinzhili
        166
    yinzhili  
       2020-05-30 12:07:00 +08:00
    楼主肯定没做过后端业务系统,所以才有这样幼稚的想法。
    pkwenda
        167
    pkwenda  
       2020-05-30 12:16:34 +08:00
    @LichMscy #165 牛,还能这样
    tonyaiken
        168
    tonyaiken  
       2020-05-30 12:55:42 +08:00
    @littleylv 当然是 400 了
    no1xsyzy
        169
    no1xsyzy  
       2020-05-30 13:31:05 +08:00
    @lscho #162 你觉得后端哪个路由判断不是字符串? JSON 不也是字符串吗?
    而且真要说这是符号判断而不是字符串判断,当然这确实有点 Lisper 味在。
    现在全网都在说必须上全站 HTTPS,路由器、运营商能给你个 404 真挺不容易的,至于你说的设备是啥我没头绪。
    至于前台服务器返回 404 本身要么仍然正确,要么就是配置错误,不单独静态目录的话,try_files 最后还是要带上反代后台的。
    lscho
        170
    lscho  
       2020-05-30 13:40:02 +08:00 via iPhone
    @no1xsyzy 抱歉我的描述不清楚,让你误解了。。我其实想了解一下#128 楼这种需求如何解决?就是注册时用户名已存在,同时后端给出推荐用户名。
    JokeEnd
        171
    JokeEnd  
       2020-05-30 13:46:11 +08:00
    上次看到类似的贴蔡徐坤还没出道
    Resource
        172
    Resource  
       2020-05-30 13:50:26 +08:00
    为什么前端开发都喜欢自己造轮子? jQuery 不够用吗?
    no1xsyzy
        173
    no1xsyzy  
       2020-05-30 13:53:46 +08:00
    @lscho #170 推荐的用户名采用单独一个 API 提供,还可以点一下切换一批
    不过仍然,这是个奇美拉。
    imn1
        174
    imn1  
       2020-05-30 13:56:50 +08:00
    我一直很希望 404 能说清究竟是 dns 问题,还是服务器找不到 path 问题

    楼主没做过后端吧?
    wingoo
        175
    wingoo  
       2020-05-30 13:58:06 +08:00
    php, restapi, design pattern, 堪称三大吵架经典
    ===
    对 rest 有啥看法?
    1.遵循公司规范
    2.没有的话, 前后端商量规范
    lscho
        176
    lscho  
       2020-05-30 14:34:32 +08:00   ❤️ 1
    @no1xsyzy 不是,还是我描述的不清楚吗?用户名存在之后你是通过什么决定前端去请求推荐用户名 api 呢?就通过接口是 404 吗?那我换一种说法。。比如常用登录地匹配上的话可能要提示用户是否需要直接登录或者找回密码,没有匹配上则要给出推荐用户名,这种如何实现呢?
    还有全站 https 和 404 没有什么关系啊,我的意思是只要能影响你 dns 的,都有可能给到 404 的结果。api 服务升级,导致 path 变化也可能导致老版本客户端 404 的。或者域名发生变化也有可能 404 。这么多情况下,客户端如何记录日志呢。
    AlisaDestiny
        177
    AlisaDestiny  
       2020-05-30 16:17:53 +08:00
    有人说 http status code 不够明确可以在 body 中加具体消息,那给这个具体消息加一个 identification code 不是更好吗?就像数据库里不管用不用得上都加一个主键一样。
    cz5424
        178
    cz5424  
       2020-05-30 16:28:52 +08:00
    @no1xsyzy 运营商给 302 挺正常的,为了广告(笑
    tohuer00
        179
    tohuer00  
       2020-05-30 16:52:05 +08:00
    真是服了有些人,在学校做了几个课程设计就能来杠出一堆一堆的。都以为自己是天才,就自己掌握了真理。
    avalon0624
        180
    avalon0624  
       2020-05-30 19:25:25 +08:00
    可能有些后端没学过 HTTP 协议
    no1xsyzy
        181
    no1xsyzy  
       2020-05-30 19:52:52 +08:00
    @lscho #176 呃,我已经说清楚了,你在尝试做一个奇美拉,或者说缝合怪,此处作为类比用没有明显区别。缝合怪通常是个设计失误。我提供的不仅仅是 “实现” 上的准则,也是 “用户体验设计” 的准则,除非你有很好的理由,不然提出不能在我所说的框架下直观地实现的本身即是设计失误。
    而奇美拉有奇美拉的做法,**如果不能确定用户名可用,你连注册请求都不应该发送**。
    no1xsyzy
        182
    no1xsyzy  
       2020-05-30 20:04:20 +08:00
    @lscho #176 举个现实世界的确应当设计为奇美拉的东西吧,Shell,以我电脑上这个 Bash 为例,你输入 ls -a,结果是调用了 ["/bin/ls", "--color=auto", "-a"],注意这里,如果 bash 不能确定 ls 是什么,根本不应该调用任何程序。在调用前 bash 必须先确定 ls 是什么。至少 ls 在 /bin 里,python 在 /usr/bin 里, ,mount_onedrive 在 ~/.bin 里,这得分清楚。
    同理,如果用户名存在,这个请求从开头就不应该发出,后端收到时简单失败即可。
    no1xsyzy
        183
    no1xsyzy  
       2020-05-30 20:07:04 +08:00
    @cz5424 #178 全站 HTTPS 就是为了避免这个的……
    lscho
        184
    lscho  
       2020-05-30 20:45:37 +08:00 via iPhone
    @no1xsyzy 我已经确定了,是你没看懂。。已经说的很明白了,是在注册的时候,去检测用户名是否存在。不去后端检测,如何能确定用户名是否已存在呢?检测用户名是否存在这个请求不应该发?
    lscho
        185
    lscho  
       2020-05-30 20:53:34 +08:00 via iPhone
    @no1xsyzy 那我再详细描述一下,在可以自定义用户名的注册场景下,用户输入用户名,需要检测用户名是否存在,如果存在,则根据用户常用登录地提供两种逻辑,在常用地,提示找回密码或者直接登录。不在常用地,推荐一组可用用户名。请问如何用 http 状态码表示用户名已存在。

    如果你觉得实现不了就是设计失误,那我只能说这是常见场景。
    yuekcc
        186
    yuekcc  
       2020-05-30 21:01:39 +08:00
    本人前端

    我所在的项目,开始的时候,接口是 restful 口味。正常时 http codo = 200,body 中直接就是数据( json ),非 200,body 返回 {errorCode: 123, message: "xxx"} 这样的结构。

    后来换人,新加的接口变成了响应码风格,正常异常都是 200 。

    一问后台,只回了一句:搞不懂原来为什么这么设计。

    我只想说,口味一样就可以了。restful 、响应码我都不介意。只要统一,一样地处理。问题是后台可否保持一致的风格。
    ChanKc
        187
    ChanKc  
       2020-05-30 21:09:32 +08:00
    如果问题仅仅在于“我如何定义我的错误并准确地告知用户”,我认真介绍一下 RFC7807 所定义的一种媒体格式:application/problem+json
    https://tools.ietf.org/html/rfc7807

    {
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    'status": 403,
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345",
    "/account/67890"]
    }

    其中 type, title, detail, status 和 instance 都是这个规范定义的成员字段,但也都是可选的,此外别的字段都是可以随意拓展的。

    其中 status 的存在就可以有效避免楼里说的 HTTP status 被篡改的问题。

    type 要求是一个指向人类可读的错误文档的 URI,如果可以确保这个 URI 不变,调用方可以对这个 URI 进行判断来确定错误。title 和 detail 则是提供了人类可读的说明。

    这个格式已经有很多语言的实现,Github 上一搜都能出来很多。而且这个格式是 RESTful 的,因为用到了超媒体。

    如果传输过程中 HTTP Body 也不幸被修改了,可能会出现的情况是 HTTP Header 的 Content-Type 也被修改,不是 application/problem+json,那么可以确定问题发生在传输过程中。如果 Content-Type 是 application/problem+json 而 body 无法按照这个格式解析,也很容易确定问题发生在传输过程中。

    不懂超媒体的就不要再黑 RESTful 了。
    no1xsyzy
        188
    no1xsyzy  
       2020-05-30 22:01:52 +08:00
    @lscho #184 先发请求确定用户名是否存在,再进行注册,很直白吧?
    我说了,这本来就是种奇美拉,或者说畸形的设计,我真的不太想跟你讨论这个,污了你我的理智。
    我说得这么清楚,你硬要说我没讲,您是真瞎还是装瞎?
    no1xsyzy
        189
    no1xsyzy  
       2020-05-30 22:03:02 +08:00
    @lscho #185 我求您了,看过别人说什么再说话,或者不要跟我说话,自己跑墙角跟空气说去,ok ?
    no1xsyzy
        190
    no1xsyzy  
       2020-05-30 22:10:31 +08:00
    @lscho #185 而且,
    实现不了就是设计失误 ✘
    只要实现上稍微有点困难就是设计失误 ✔

    仅以您浅薄的见识来断定常见场景是不是有点自大了?
    你难道没有发现这种情况下任何人可以通过你放出的界面来知晓任何一名用户的常用地?
    难道明显违法就是所谓常见场景?
    vizee
        191
    vizee  
       2020-05-30 22:23:26 +08:00
    你的业务不是 http,不够用不是很正常的吗?说的前端真会处理 code 似的?
    lscho
        192
    lscho  
       2020-05-30 22:34:35 +08:00
    @no1xsyzy 问的意思就是“先发请求确定用户名是否存在,再进行注册”,这个请求你用什么状态码来表示用户已存在,并且决定后续走流程 A 还是流程 B 。我们说的不够清楚吗?

    说了这么多您还没有个准确的回答,其实我心里已经有答案了。

    “你难道没有发现这种情况下任何人可以通过你放出的界面来知晓任何一名用户的常用地?”,你凭什么可以知晓任何用户的常用地?你只能得到当前 ip 不是常用地,想知道常用地,必须准确的模拟出该用户的常用 ip 甚至常用设备来请求,才能得到是真实 IP 的结果。

    回到标题“为什么后端开发都喜欢自己定义 responseCode ? HTTP 状态码不够用吗?”,答案就是 http 状态码根本无法代替业务状态码来使用,http 状态码真的不够用,除非你的业务够简单。

    不再回复了。
    no1xsyzy
        193
    no1xsyzy  
       2020-05-30 23:12:52 +08:00
    @lscho #192 这是业务的内容,极端点说,这就是个 query,用数据体返回值即可。
    你不会觉得我说只要 HTTP 状态码是说数据体一点都不要吧…… 所以说你该从头把我说的话看一遍,返回值并不是状态码。

    类比到函数调用上去:
    状态码决定 return value 的 continuation (比如应当被某个 try catch 拿到还是被上层调用拿到还是其他什么)而不是 return value 本身
    no1xsyzy
        194
    no1xsyzy  
       2020-05-30 23:17:58 +08:00
    @lscho #192 至于如何泄漏,简单点把所有地区模拟一遍就行了。虽然不是能够直接遍历获取的但仍然是旁路泄漏。
    方便一点的,可以通过字典轻易地遍历出同 IP 的其他用户 —— 摸鱼探测器 kana ?
    no1xsyzy
        195
    no1xsyzy  
       2020-05-30 23:34:28 +08:00
    @lscho #192 回头看了下 #185 前面大段复读影响了我的阅读。没看到这句 “如何用 http 状态码表示用户名已存在。”

    想了想,被问到逻辑偏掉了…… 再从头描述一下这个准则吧,“状态码即续延”。
    所谓状态码、无论是 HTTP 状态码还是业务状态码,不应参与任何业务逻辑判断,而仅仅是表示 “接下来让哪个代码块来处理这个回应”
    换句话说,就是 FSM 中的 “状态”。
    zhuangzijun1996
        196
    zhuangzijun1996  
       2020-05-30 23:51:29 +08:00 via Android   ❤️ 1
    为什么前段都喜欢把业务状态码和通信状态码混在一起
    bsg1992
        197
    bsg1992  
       2020-05-31 00:48:20 +08:00
    @no1xsyzy 别人说 A 你答 C 。
    首先 http code 仅仅是代表传输协议的上的一种状态标识和业务没有关系。
    一个业务接口通讯方式不是只有一种,如果用的不是 http 协议没有 http code 如何标识业务状态
    有的业务需要根据后端返回的状态码来进行相应的操作。比如说提现场景,申请提现业务方更改了规则导致业务提现失败,需要根据相应的规则进行不同的跳转,这个时候你不用 code 做标识,难道用 msg? 还是说按照您的逻辑来说这个业务的处理方式不合理?
    还有和别人进行交流的时候请不要用一些亚文化的词语和梗
    no1xsyzy
        198
    no1xsyzy  
       2020-05-31 01:09:22 +08:00
    @bsg1992 #197 “需要根据相应的规则进行不同的跳转” 不就是续延的意思吗?
    我不是说了(#109 )用 Symbol 吗? code 本身就是旧时代产物,业务层面一切 code 应当由 symbol 取代,没有很好的依据随便用 code 的全部当作 premature optimization 。

    亚文化词语和哏…… 我细看也只发现了个不影响整体含义的 kana ;其他有嫌疑的,比如奇美拉是希腊神话,算不得亚文化,其他也没什么亚文化,倒是可能你没文化。
    back0893
        199
    back0893  
       2020-05-31 01:28:45 +08:00
    请求确定用户名是否存在
    这是不是很常见的需求
    或者换成电子邮箱,你不能不去判断邮箱不重复吧
    cz5424
        200
    cz5424  
       2020-05-31 10:28:07 +08:00 via iPhone
    不考虑后端工作量的所有假设都是伪命题
    1  2  3  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3063 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 13:47 · PVG 21:47 · LAX 05:47 · JFK 08:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.