param
V2EX  ›  问与答

想给所有的业务异常一个统一固定的 HTTP 状态码,用什么合适? 403? 409? 422?

  •  1
     
  •   param · Sep 1, 2023 · 4494 views
    This topic created in 1160 days ago, the information mentioned may be changed or developed.

    http 状态码能不能用-1 的。

    不要 200 ,那样我就要在 response 再包一层。 我想给业务异常统一固定的 HTTP 状态码,例如 403 ,那么我遇到 403 才会拆开看里面的业务异常,在 403 的 response 里返回大写字母格式的错误码以及 err msg 。如果遇到 200 ,就默认没有异常,不需要拆开了。

    业务异常指的是,诸如「未完成的订单不允许评论」之类的

    403 经常被认为是「权限不够,换个身份操作就可以成功」的意思,但它其实应该是「 forbidden 」,没有说明是权限不够而 forbidden ,或者其他原因的 forbidden 。具体原因还是可以在 body 里看。

    这个问题在这里好像吵得很厉害,我不想对 200 再封一层,同时也需要自定义的状态码,这完全不矛盾呀。

    32 replies  •  2023-09-07 23:25:49 +08:00
    dzdh
    dzdh
    Sep 1, 2023
    1
    非要定一个比较合理的规范的话。可以考虑 guzzle 的封装

    由于提交的参数有问题的 4xx

    - 资源不存在( id?=x ) 404
    - 缺少参数,参数不合法 400
    - 不能操作这个资源 (?id=xx ) 403

    class X extends Exception {}

    class X404 extends X{}

    class X400 extends X{}

    class ResourceNotFound extends X404 {}
    param
    param
    OP
    Sep 1, 2023
    2
    @dzdh 如果要细分的话,很容易选择困难。。所以业务层的异常还是统一同一个码就好了。
    otakustay
    otakustay
    Sep 1, 2023
    3
    毫无疑问的 400 吧
    dzdh
    dzdh
    Sep 1, 2023
    4
    @param

    我是统一 200 code, result, mark, data :doge:
    xfn
    xfn
    Sep 1, 2023
    5
    我的理解是如果是调用方的问题返回 4xx ;服务提供方的问题返回 5xx ;你这种情况应该是调用方没有满足业务期望的条件,个人认为 400 比较合适
    mritd
    mritd
    Sep 1, 2023
    6
    感觉应该 400 好点吧, 不过确实很多业务系统喜欢 200 all in... 他们却是也有一些理由, 就是某些 http 库非 200 可能抛 异常啥的; 不过我没写过客户端还是不太了解, 我个人理解 HTTP CODE 应该是更高层次的、笼统一点的错误提示, 而内部 body 可以附加业务层次的特定错误描述.
    param
    param
    OP
    Sep 1, 2023
    7
    @otakustay 请求格式错误才是 400 吧,例如本该用 application/json 的却用了 multipart/form-data
    otakustay
    otakustay
    Sep 1, 2023
    8
    @param #7 所有客户端的错误都是 400 ,请求格式错误 415
    fredweili
    fredweili
    Sep 1, 2023
    9
    除了 code ,还能再传一个 header
    param
    param
    OP
    Sep 1, 2023
    10
    @fredweili 咦,这么说,错误码直接放 header 就可以
    param
    param
    OP
    Sep 1, 2023
    11
    @fredweili 那问题来了,header 用什么名好呢。
    grissom
    grissom
    Sep 1, 2023
    12
    那明显是 http 定义的以外的任意 code 了
    28Sv0ngQfIE7Yloe
    28Sv0ngQfIE7Yloe
    Sep 1, 2023
    13
    CodeCodeStudy
    CodeCodeStudy
    Sep 1, 2023❤️2
    14
    不要修改 HTTP 状态码,HTTP 状态码应该是由 Nginx 之类的 web 服务器来掌控,业务上的状态应该自己搞一套状态码来表示。
    如果是 401 的话,比如 Nginx 设置了 auth_basic ,需要输入用户名和密码,用户名和密码不对的话就是 401 。
    如果是 403 ,那就是不给看就不给看。
    个人建议使用自定义的业务的状态,用大于 1000 的数字来表示。
    zjw7sky
    zjw7sky
    Sep 1, 2023
    15
    这样是不是不利于拓展
    iOCZ
    iOCZ
    Sep 1, 2023❤️4
    16
    建议区分 http status code 和 business status code
    loading
    loading
    Sep 1, 2023
    17
    我觉得合理的方法是:
    api 正确响应了就返回 200 ,把 http 状态码留给网络问题。

    api 的错误,例如找不到货物(不是 url 找不到的 404 ),就 HTTP 200 ,然后返回的数据一般是这样:

    {
    code:404,
    msg:'找不到货物',
    data:[]
    }

    其中 code 部分参考 http 的码来做,msg 是给人看的信息,或者作为提示信息。

    我非常喜欢这种方式,希望能帮到你。
    dallaslu
    dallaslu
    Sep 1, 2023
    18
    按规范来吧,只用标准的 http 状态码,其他业务上的错误码请在 body 里自行定义
    QlanQ
    QlanQ
    Sep 1, 2023❤️2
    19
    名字就叫 http 状态码,为什么要和业务相关?
    如果你用户名密码错误,这是 业务上的错误,http 的请求是成功的

    从后续处理上来讲,前端在遇到不是 200 的情况的下,都是不解析具体 响应的,不是 200 就被认为是 请求有问题,
    和断网类似
    zerduo
    zerduo
    Sep 1, 2023
    20
    那你不随便嘛,只要是 http 状态码,统一就行,跟前端定好了无所谓,一个数字而已
    yolee599
    yolee599
    Sep 1, 2023 via Android
    21
    http 请求到达了你业务程序,你就应该返回 200 ,业务代码再在 body 中单独定义
    sujin190
    sujin190
    Sep 1, 2023 via Android
    22
    body 结构不一致才是真的坑死人,每次遇到这种都觉得这么干的人真是脑子进水了
    Masoud2023
    Masoud2023
    Sep 1, 2023
    23
    非要用 http 状态码就老老实实 RFC

    不要自己造状态码,body 里 errorCode 不磕碜,自己乱造小心到时候各种中间件找你麻烦
    clf
    clf
    Sep 1, 2023
    24
    只用标准的 http 状态码,业务异常则是 Http 200 ,但 body 的 code 返回其他的。
    fivesmallq
    fivesmallq
    Sep 1, 2023
    25
    参考 stripe 设计 https://stripe.com/docs/api/errors?lang=curl

    ```sh
    curl https://api.stripe.com/v1/payouts \
    -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
    -d amount=11a00 \
    -d currency=usd
    {
    "error": {
    "code": "parameter_invalid_integer",
    "doc_url": "https://stripe.com/docs/error-codes/parameter-invalid-integer",
    "message": "Invalid integer: 11a00",
    "param": "amount",
    "request_log_url": "https://dashboard.stripe.com/test/logs/req_H7WCCMvEpRyv9s?t=1693547819",
    "type": "invalid_request_error"
    }
    }

    ```

    也可以不加 error 那一层,直接返回里面的内容。
    scung
    scung
    Sep 1, 2023
    26
    用 HTTP 418 状态码😊
    TPOB
    TPOB
    Sep 1, 2023
    27
    现在大家的用法其实是把 http 当传输层协议在用,那 http 的状态码就应该统一是 200 (传输没有异常)。业务的异常就放在 body 里面才对
    cylx3124
    cylx3124
    Sep 1, 2023❤️1
    28
    https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/http/HttpStatusCode.java#L39C2-L77C20

    https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/http/HttpStatus.java#L36C1-L424C95

    Spring 文档给出了对的 http code 详细解释,建议先看一下 Spring 对 http status 的定义,然后思考下 4xx 客户端异常、5xx 服务端异常和业务异常的区别,想明白以后你的问题自己心里应该就会有答案。
    zhzy0077
    zhzy0077
    Sep 1, 2023
    29
    要么你就正经按照错误类型去找最合适的 http code ,虽然对于绝大多数业务 4xx 和 5xx 是绝对不够用的。
    要么你就干脆一律 200 ,然后用 flag 去标有没有成功。
    一半一半的容易把自己和同事绕进去
    wu00
    wu00
    Sep 1, 2023
    30
    符合规范的只用了这几个,基本上是网关层/代码底层控制的
    401 ,403 ,404 ,415 ,502 ,500

    开发中约定俗成的由开发人员控制的就两个
    200 ,成功一律 200 ,不区分 201 、204 等等
    400 ,业务异常一律 400 ,包一个对象定义异常类型{errorCode, errorData, errorMessage}

    真要按照标准规范无疑是找罪受...
    agagega
    agagega
    Sep 1, 2023 via iPhone
    31
    以前接手过一个 php 项目,错误统一 404…
    param
    param
    OP
    Sep 7, 2023
    32
    @CodeCodeStudy 没错啊,我不是说了用自定义的业务状态码吗。只是客户端要在遇到业务异常时才需要去看业务状态码,所以需要一个 http 状态码来表示出现了业务异常。

    @iOCZ 我不是已经区分了吗。我 http 状态码只是用来标记有没有出现业务异常,而具体的业务异常肯定是用业务状态码表示啊。

    @dallaslu 我不是说了把业务异常放在 body 里定义了吗。只是我需要先判断是否成功,再决定要不要拆开 body 看业务异常。如果是 200 我就不用拆开看 body 里的东西了。

    @TPOB 对啊,业务异常放在 body 啊。现在要用一个 http 状态码表示业务是否成功,不成功的话就看 body 里给了什么业务异常。

    楼上已经说了,用 400 了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2979 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 128ms · UTC 10:47 · PVG 18:47 · LAX 02:47 · JFK 05:47
    ♥ Do have faith in what you're doing.