干点实事儿:api 应该怎么写

干点实事儿:api 应该怎么写

以下内容均为我这几年工作经验的个人理解以及对一些公开接口的参考。如果有不对的地方欢迎交流,在评论区或者 i@mitkimi.com 都可以

接口地址

无论是模块化设计还是为服务,都应该遵循一定的接口地址的标准

接口域名

接口域名应该至少考虑测试环境、生产环境两个域名,有时如果还有前后端不在同一个办公室并且没有 vpn 的情况时,可能需要额外部署一个开发环境用于联调
例如:

  • 开发域名:dev.api.yourdomain.com
  • 测试域名:test.api.yourdomain.com
  • 生产域名:api.yourdomain.com

可以使用三级域名用于语义化表示接口用途,用 apireach 表示服务端,当然也可以选择你喜欢的其他词汇,例如 serve

完整 URL

http(s)://{{主机}}/{{微服务}}/{{模块}}/{{类}}/{{动作}}?sign={{签名}}

以上签名、微服务是可选的

请求方法

我们建议请求方法对应数据库的 CURD 动作,但这不是强制的

方法类型对应数据库操作备注
GET查询数据查R: query-
POST新增数据增C: create-
PUT更新数据改U: update-
DELETE删除数据删D: delete逻辑删除时也可以使用

层和返回

一般情况下,我们认为应该从 http 层开始,当返回 http 状态码为 200 时,才进入到下一层:报文
报文状态码为 0 时,在应该在 data 中返回数据

HTTP

我们不建议使用 HTTP 状态作为数据查询状态返回给前端,而是另包一层。例如:
假设我们查询数据时发现当前的筛选条件查出的数据长度为 0,如果在返回 HTTP 按照 404 的方式返回给前端,前端研发就很难判断这个 404 是没有查到数据还是接口地址搞错了
因此我们应该统一使用 200 进行返回,如果查询的值为空,可以在查询成功的情况下返回一个状态码

报文

首先,从外壳的角度考虑,我们应该返回状态码、给研发人员看的服务端信息和返回数据,例如:

{
  "code": 0,
  "message": "query ok",
  "data": {
    "count": 1098,
    "page": 1,
    "pageSize": 10,
    "list": [
      {
        "id": 1,
        "name": "zhang san",
        "age": "18"
      }
    ]
  }
}

或者:

{
  "code": -9,
  "message": "authority failed",
  "data": {}
}

状态码

我们建议所有的报错的状态码使用负数,用负数代表报错,用非负数代表没有报错
理由是,我们认为“状态码”不是“错误码”,而正常的状态对应数轴的正方向,所以用负值表示反

在状态码的设计方面,我们也建议分门别类。例如:

状态码范围对应用途举例
-1 ~ -9鉴权用-9: 未登录或鉴权失败
-1001 ~ -1009查询参数错误-1001: 有必填参数未传递
.........

所有正常的返回使用 0 或正整数。
一般情况下,我们可能不会区分更多的正常状态,但是

从数据的层面我们认为返回的内容应该尽量的简洁、明晰,不应该把所有的内容全都返回给前端

信息

传递的信息是给研发人员联调使用的,真正反馈给用户看的信息,应该由前端根据错误代码和信息给出

数据

返回的数据中,无论查询的是列表还是单个数据,都应该使用列表(数组)返回
除此之外,当查询的是列表时,还应该返回总可用条数,以及页码和页长
以下例子省略报文外壳

"data": {
  "count": 92,
  "page": 10,
  "pageSize": 10,
  "list": [
    {
      "id": 91,
      "name": "小王"
    },
    {
      "id": 92,
      "name": "小李"
    }
  ]
}

安全

数据的传输安全非常重要,如果有数据被拦截,并且模拟用户身份向后端发起攻击,再好的服务器可能也扛不住。

token

有时候我们需要允许一个用户从多个不同终端登录。这时候鉴权需要一个 token,当然也可以做到例如扫码登录等功能。

JWT [JSON Web Token] 是目前最流行的跨域认证解决方案,可以用来认证/单点登录等

token 应该埋在请求头(http header)中,在后续的操作中,后端应该在过滤器(有的是中间件)中检查 token 是否符合接受请求的安全标准

数字签名

我们建议每个项目接口都应该加上数字签名,
数字签名是前后端使用某种约定的规则,根据发送的参数、时间戳和一些密钥等计算出来的不可逆的无意义代码,前端、后端分别计算比对,当参数被修改,数字签名无法对上的情况下,在后端的过滤器(中间件)中做拦截,可以极大程度的挡住攻击者通过后端程序漏洞修改数据库,一定程度上保证了数据安全

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×