文章目录
概念
Restful API用来规范应用如何在HTTP层与API提供方进行数据交互 。
Restful API描述了HTTP层里客户端和服务器端的数据交互规则:客户端通过向服务器端发送HTTP(S)请求,接收服务器的响应,完成一次HTTP交互。这个交互过程中,REST架构约定两个重要方面就是HTTP请求的所采用方法,以及请求的链接。
在请求层面,Restful API规范可以简单粗暴抽象成以下两个规则:
- 请求API的URL表示用来定位资源
- 请求的METHOD表示对这个资源进行的操作
API的URL
版本号
在Restful API中,API应当尽量兼容之前的版本。Web端很容易为了适配服务端的新的API接口进行版本升级,而Android、IOS等客户端必须通过用户主动升级产品到新版本,才能适配新接。
为了解决这个问题,在设计Restful API时一般情况下会在URL中保留版本号,并同时兼容多个版本:
【GET】 /v1/users/{user_id} // 版本 v1 的查询用户列表的 API 接口
【GET】 /v2/users/{user_id} // 版本 v2 的查询用户列表的 API 接口
现在可以在不改变V1版本的接口情况下,新增V2版本的接口满足新的业务需求。服务端会同时兼容多个版本,但是同时维护版本过多也会成为不小的负担。
常见的做法是,不维护全部的兼容版本,而是只维护最新的几个兼容版本,例如维护最新的三个兼容版本。在一段时间后,大部分的用户升级到新的版本后,废弃一些使用量较少的服务端老版本的API接口,并要求使用产品老旧版本的用户墙纸升级。
不合理的URL
URL用来定位资源,跟要进行的操作区分开,这就意味这URL不该有任何动词
下面示例中的get
、create
、search
等动词,都不应该出现在REST架构的后端接口路径中。在以前,这些接口中的动名词通常对应后台的某个函数。比如:
/api/getUser
/api/createApp
/api/searchResult
/api/deleteAllUsers
当我们需要对单个用户进行操作时,根据操作的方式不同可能需要下面的这些接口:
/api/getUser
// 用来获取某个用户的信息,还需要以参数方式传入用户 id 信息)
/api/updateUser
// 用来更新用户信息
/api/deleteUser
// 用来删除单个用户
/api/resetUser
// 重置用户的信息
这样的弊端在于:
- URL更长了
- 对一个资源实体进行不同的操作就是一个不同URL,造成URL过多难以管理。
其实当你回过头看「URL」这个术语的定义时,更能理解这一点。URL的意思是统一资源定位符,这个术语已经清晰的表明,一个URL应该用来定位资源,而不应该掺入对操作行为的描述。
Restful的URL
在REST架构的URL应该是这个样子:
- URL中不应该出现任何表示操作的动词,链接只用于对应资源;
- URL中应该单复数区分,推荐的实践是永远只用复数;比如
GET /api/users
表示获取用户的列表;如果获取单个资源,传入ID,比如/api/users/123
表示获取单个用户的信息; - 按照资源的逻辑层级,对URL进行嵌套,比如一个用户属于某个团队,而这个团队也是众多团队之一;那么获取这个用户的接口可能是这样:
GET /api/teams/123/members/234
// 表示获取 id 为 123 的小组下,id 为234 的成员信息
按照类似的规则,可以写出如下的接口:
/api/teams
// 对应团队列表
/api/teams/123
// 对应 ID 为 123 的团队
/api/teams/123/members
// 对应 ID 为 123 的团队下的成员列表
/api/teams/123/members/456
// 对应 ID 为 123 的团队下 ID 为 456 的成员
特殊情况
有的时候一个资源变化难以使用标准的Restful API来命名,可以考虑使用一些特殊的Actions命名。比如,“密码修改”这个接口的命名很难完全使用名词来构建路径,此时可以引入Action:
PUT /v1/users/{user_id}/password/actions/modify
// 密码修改
大小写
根据RFC3986定义,URL是大小写明暗的,所以为了避免歧义,尽量使用小写字母。
API的请求方法
在很多系统中,几乎只用GET和POST方法来完成了所有的接口操作。这个行为类似于全用<div>