现在在开发中前后端都是分离开发,后端提供接口给前台,RESTful 架构,就是目前最流行的一种互联网软件架构,也相当于是接口规范
关于「能愿动词」的使用
为了避免歧义,文档大量使用了「能愿动词」,对应的解释如下:
必须 (MUST)
:绝对,严格遵循,请照做,无条件遵守一定不可 (MUST NOT)
:禁令,严令禁止应该 (SHOULD)
:强烈建议这样做,但是不强求不该 (SHOULD NOT)
:强烈不建议这样做,但是不强求可以 (MAY)
和可选 (OPTIONAL)
:选择性高一点,在这个文档内,此词语使用较少
协议
客户端在通过 API
与后端服务通信的过程中,应该
使用 HTTPS
协议
域名
API
应该部署在专用域名之下,应尽可能保持足够简单。如果确定API
很简单,不会有进一步扩展,可以考虑放在主域名下,这里有两个常见的 URL
根例子:
- api.example.com/*
- example.com/api/*
版本(Versioning)
所有的 API
必须保持向后兼容,你 必须
在引入新版本 API
的同时确保旧版本 API
仍然可用。所以 应该
为其提供版本支持
目前比较常见的两种版本号形式:
在 URL 中嵌入版本编号,这种做法是版本号直观、易于调试
api.example.com/v1/*
另一种做法是,将版本号放在 HTTP Header
头中,但不如放入URL方便和直观
路径(Endpoints)
路径又称”终点、端点”(endpoint),表示API的具体网址
端点就是指向特定资源或资源集合的 URL
。在端点的设计中,你 必须
遵守下列约定:
- URL 的命名
必须
全部小写 - URL 中资源(
resource
)的命名必须
是名词,并且必须
是复数形式 必须
优先使用Restful
类型的 URL- URL
必须
是易读的 - URL
一定不可
暴露服务器架构
至于 URL 是否必须使用连字符(-
) 或下划线(_
),不做硬性规定,但 必须
根据团队情况统一一种风格
来看一个反例
- https://api.example.com/getUserInfo?userid=1
- https://api.example.com/getusers
- https://api.example.com/sv/u
- https://api.example.com/cgi-bin/users/get_user.php?userid=1
再来看一个正列
- https://api.example.com/zoos
- https://api.example.com/animals
- https://api.example.com/zoos/{zoo}/animals
- https://api.example.com/animal_types
- https://api.example.com/employees
HTTP 动词
对于资源的具体操作类型,由 HTTP
动词表示。常用的 HTTP
动词有下面五个(括号里是对应的 SQL
命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
其中
- 删除资源
必须
用DELETE
方法 - 创建新的资源
必须
使用POST
方法 - 更新资源
应该
使用PUT
方法 - 获取资源信息
必须
使用GET
方法
还有两个不常用的HTTP动词
- HEAD:获取资源的元数据
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的
下面是一些例子:
请求方法 | URL | 描述 |
GET | /zoos | 列出所有的动物园(ID和名称,不要太详细) |
POST | /zoos | 新增一个新的动物园 |
GET | /zoos/{zoo} | 获取指定动物园详情 |
PUT | /zoos/{zoo} | 更新指定动物园(整个对象) |
PATCH | /zoos/{zoo} | 更新动物园(部分对象) |
DELETE | /zoos/{zoo} | 删除指定动物园 |
GET | /zoos/{zoo}/animals | 检索指定动物园下的动物列表(ID和名称,不要太详细) |
GET | /animals | 列出所有动物(ID和名称)。 |
POST | /animals | 新增新的动物 |
GET | /animals/{animal} | 获取指定的动物详情 |
PUT | /animals/{animal} | 更新指定的动物(整个对象) |
PATCH | /animals/{animal} | 更新指定的动物(部分对象) |
GET | /animal_types | 获取所有动物类型(ID和名称,不要太详细) |
GET | /animal_types/{type} | 获取指定的动物类型详情 |
GET | /employees | 检索整个雇员列表 |
GET | /employees/{employee} | 检索指定特定的员工 |
GET | /zoos/{zoo}/employees | 检索在这个动物园工作的雇员的名单(身份证和姓名) |
POST | /employees | 新增指定新员工 |
POST | /zoos/{zoo}/employees | 在特定的动物园雇佣一名员工 |
DELETE | /zoos/{zoo}/employees/{employee} | 从某个动物园解雇一名员工 |
过滤信息(Filtering)
如果记录数量很多,服务器不可能都将它们返回给用户。API 应该
提供参数,过滤返回结果
下面是一些常见的参数:
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?page=2&per_page=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?animal_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复
比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的
所有 URL
参数 必须
是全小写,必须
使用下划线类型的参数形式
分页参数 必须
固定为 page
、per_page
响应(Response)
所有的 API
响应,必须
遵守 HTTP
设计规范,必须
选择合适的 HTTP
状态码。一定不可
所有接口都返回状态码为 200
的 HTTP
响应,如:
HTTP/1.1 200 ok
Content-Type: application/json
Server: example.com
{
"code": 0,
"msg": "success",
"data": {
"username": "username"
}
}
或者
HTTP/1.1 200 ok
Content-Type: application/json
Server: example.com
{
"code": -1,
"msg": "该API不存在",
}
下表列举了常见的 HTTP 状态码
状态码 | 描述 |
1xx | 代表请求已被接受,需要继续处理 |
2xx | 请求已成功,请求所希望的响应头或数据体将随此响应返回 |
3xx | 重定向 |
4xx | 客户端原因引起的错误 |
5xx | 服务端原因引起的错误 |
只有来自客户端的请求被正确的处理后才能返回 2xx 的响应,所以当 API 返回 2xx 类型的状态码时,前端 必须 认定该请求已处理成功
必须强调的是,所有 API
一定不可
返回 1xx
类型的状态码。当 API
发生错误时,必须
返回出错时的详细信息。目前常见返回错误信息的方法有两种:
- 将错误详细放入
HTTP
响应首部 - 直接放入响应实体中
日常观赏