Skip to content

Instantly share code, notes, and snippets.

@QuantumGhost
Last active September 28, 2022 16:07
Show Gist options
  • Save QuantumGhost/72e9615a745ce7e93c58952ff4ec328a to your computer and use it in GitHub Desktop.
Save QuantumGhost/72e9615a745ce7e93c58952ff4ec328a to your computer and use it in GitHub Desktop.

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

又是基于 HTTP 的 API 设计问题

我个人的想法是:

  1. RESTful 和 RPC 风格各有优劣,具体场景具体分析,但是整体一致最重要,不一致的 API 始终是最糟糕的。

  2. 如果要添加错误码,错误码最好放在 HTTP 头里面,这样可以在不读取 payload 的情况下判断是否存在错误

    例如:X-Error-Code: 10001 或者 X-Error-Code: OUT_OF_CREDIT

    注意 HTTP 头的值只能使用 ASCII 码的子集

  3. 如果你使用 RESTful 风格的 API design,那么在成功时应该尽量 避免额外包裹响应数据,也就是使用:

    {
        "id": 1,
        "name": "John"
    }

    避免:

    {
        "data": {
            "id": 1,
            "name": "John Due"  
        }
    }

    在失败时应该有固定的响应结构,例如

    {
        // toast 消息
        "message": "余额不足",
    }

    在业务需要的情况下,失败时可以有更多的额外数据,比如

    {
        "message": "表单错误",
        // 额外的错误内容,提供给前端在代码内部进行判断
        "extra": [
            {
                "type": "validation_error",
                "field_name": "username",
                "message": "用户名不能包含 -"
            },
            {
                "type": "validation_error",
                "field_name": "password",
                "message": "密码不能少于 6 位"
            }
        ]
    }

    (这部分参考了 gRPC 的错误接口设计)

  4. 如果你只想要 RPC 的语义,那么可以考虑按 RPC 的方式来设计 API,或者直接上 gRPC

关于错误码,我个人的思考是:

  1. 避免定义太多错误码,如 Google API design guide 所说, 定义太多的错误码非常不友好,实际上开发者也不会检查那么多错误。
  2. 如果是某个场景出错时需要在程序上判断错误类型,可以把它放到响应的 extra 字段中,由前端进行判断。
  3. 如果很多场景都有共同的需要在代码中判断的错误类型时,可以为它添加一个错误码

总体上来说,我个人的设计原则是:如果一个接口前端不需要在代码中判断错误类型并进行处理,就不需要加入错误码,也不需要在 extra 字段加入额外的错误描述信息。

以及,IETF 有一个关于 HTTP API 错误的 RFC,也可以拿来参考。

(居然写了这么多 = =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment