主页

索引

模块索引

搜索页面

2.1.9. 接口规范

RESTful API设计原则

URI 设计时,应该遵循的一些规范:

1. 资源名使用名词而不是动词,并且用名词复数表示
    资源分为 Collection 和 Member 两种:
    Collection:一堆资源的集合
        例如我们系统里有很多用户(User), 这些用户的集合就是 Collection
        Collection 的 URI 标识应该是 域名 / 资源名复数 ,
        例如 https://iam.api.marmotedu.com/users
    Member:单个特定资源
        例如系统中特定名字的用户,就是 Collection 里的一个 Member
        Member 的 URI 标识应该是 域名 / 资源名复数 / 资源名称
        例如 https://iam.api.marmotedu/users/admin
2. URI 结尾不应包含 /
3. 统一使用一种格式
    如:URI 中使用下划线- 还是中杠线-
4. URI 路径用小写,不要用大写
5. 避免层级过深的 URI
    超过 2 层的资源嵌套会很乱,建议将其他资源转化为 ? 参数,
    比如:
        /schools/tsinghua/classes/rooma/students/zhang  # 不推荐
        /students?school=qinghua&class=rooma            # 推荐

在实际的 API 开发中,可能你会发现有些操作不能很好地映射为一个 REST 资源,这时候,你可以参考下面的做法:

1. 将一个操作变成资源的一个属性
    比如想在系统中暂时禁用某个用户:
    /users/zhangsan?active=false
2. 将操作当作是一个资源的嵌套资源
    比如一个 GitHub 的加星操作:
      PUT /gists/:id/star     # github star action
      DELETE /gists/:id/star  # github unstar action
3. 如果以上都不能解决问题,有时可以打破这类规范
    比如登录操作,登录不属于任何一个资源,URI 可以设计为:/login

REST 资源操作映射为 HTTP 方法

对资源的操作应该满足安全性和幂等性:

1. 安全性: 不会改变资源状态,可以理解为只读的。
2. 幂等性: 执行 1 次和执行 N 次,对资源状态改变的效果是等价的

使用 HTTP 方法的时候,有以下两点需要你注意:

1. GET 返回的结果,要尽量可用于 PUT、POST 操作中
  例如,用 GET 方法获得了一个 user 的信息,调用者修改 user 的邮件,然后将此结果再用 PUT 方法更新
  这要求 GET、PUT、POST 操作的资源属性是一致的。
2. 如果对资源进行状态 / 属性变更,要用 PUT 方法,POST 方法仅用来创建或者批量删除这两种场景

批量删除的需求可以通过下面三种方式来解决:

1. 发起多个 DELETE 请求
2. 操作路径中带多个 id,id 之间用分隔符分隔,例如:DELETE /users?ids=1,2,3
3. 直接使用 POST 方式来批量删除,body 中传入需要删除的资源列表

统一的返回格式

  • 一个系统的 RESTful API 会向外界开放多个资源的接口,每个接口的返回格式要保持一致。

  • 每个接口都会返回成功和失败两种消息,这两种消息的格式也要保持一致。

  • 返回的格式没有强制的标准,你可以根据实际的业务需要返回不同的格式。

API 版本管理

API 版本有不同的标识方法,在 RESTful API 开发中,通常将版本标识放在如下 3 个位置:

1. URL 中
  比如 /v1/users
2. HTTP Header 中
  比如 Accept: vnd.example-com.foo+json; version=1.0
3. Form 参数中
  比如 /users?version=v1

其他

API 命名:

驼峰命名法 (serverAddress)
蛇形命名法 (server_address)
脊柱命名法 (server-address)

分页:

在列出一个 Collection 下所有的 Member 时,应该提供分页功能
例如 /users?offset=0&limit=20(limit,指定返回记录的数量;offset,指定返回记录的开始位置)
引入分页功能可以:
  减少 API 响应的延时
  同时可以避免返回太多条目
  导致服务器 / 客户端响应特别慢
  甚至导致服务器 / 客户端 crash 的情况

过滤:

如果用户不需要一个资源的全部状态属性,可以在 URI 参数里指定返回哪些属性
例如 /users?fields=email,username,address

排序:

用户很多时候会根据创建时间或者其他因素,列出一个 Collection 中前 100 个 Member
这时可以在 URI 参数中指明排序参数,例如 /users?sort=age,desc。

搜索:

当一个资源的 Member 太多时,用户可能想通过搜索,快速找到所需要的 Member,
或着想搜下有没有名字为 xxx 的某类资源,这时候就需要提供搜索功能。
搜索建议按模糊匹配来搜索。

域名:

API 的域名设置主要有两种方式:
1. https://marmotedu.com/api
  这种方式适合 API 将来不会有进一步扩展的情况
  比如刚开始 marmotedu.com 域名下只有一套 API 系统,未来也只有这一套 API 系统
2. https://iam.api.marmotedu.com
  如果 marmotedu.com 域名下未来会新增另一个系统 API
  这时候最好的方式是每个系统的 API 拥有专有的 API 域名,
  比如:storage.api.marmotedu.com,network.api.marmotedu.com
  腾讯云的域名就是采用这种方式

RPC API

RPC 调用具体流程如下:

1. Client 通过本地调用,调用 Client Stub
2. Client Stub 将参数打包(也叫 Marshalling)成一个消息,然后发送这个消息
3. Client 所在的 OS 将消息发送给 Server
4. Server 端接收到消息后,将消息传递给 Server Stub
5. Server Stub 将消息解包(也叫 Unmarshalling)得到参数
6. Server Stub 调用服务端的子程序(函数),处理完后,将最终结果按照相反的步骤返回给 Client

负责调用参数和返回值的流化(serialization)、参数的打包和解包,以及网络层的通信:

1. Client 端一般叫 Stub
2. Server 端一般叫 Skeleton

OpenAPI

  • OpenAPI 是一个 API 规范,它的前身叫 Swagger 规范,通过定义一种用来描述 API 格式或 API 定义的语言,来规范 RESTful 服务开发过程,目前最新的 OpenAPI 规范是 OpenAPI 3.0(也就是 Swagger 2.0 规范)

  • OpenAPI 是一个 API 规范,Swagger 则是实现规范的工具

OpenAPI 规范规定了一个 API 必须包含的基本信息:

1. 对 API 的描述,介绍 API 可以实现的功能
2. 每个 API 上可用的路径(/users)和操作(GET /users,POST /users)
3. 每个 API 的输入 / 返回的参数
4. 验证方法
5. 联系信息、许可证、使用条款和其他信息

参考

主页

索引

模块索引

搜索页面