RESTful API接口规范
前言
为了前后端分工明确,对接流畅,确保可读性和扩展性以及高可用、一致性,特约定下述无状态 RESTful API 接口规范。
主要原则
RESTful API 统一约束客户端和服务器之间的接口。简化和分离系统架构,使每个模块独立。
- 请求中使用 URI 定位资源
- 用 HTTP Verbs[动词](GET、POST、PUT、PATCH、DELETE)描述操作(具体表现形式)
- 数据传递(默认)采用:Content-Type: application/json; charset=utf-8
- 单一职责原则:每个接口只负责一个职责,各个职责的接口改动,不影响其它接口
- 接口隔离原则:用多个专门的接口,而不使用单一的总接口
RESTful 资源操作
RESTful 中根据操作资源的不同,使用不同的 http 方法。
- 幂等性:对同一 REST 接口的多次访问,得到的资源状态是相同的;
- 安全性:对该 REST 接口访问,不会使服务器端资源的状态发生改变。
| http 方法 | 资源操作 | 幂等 | 安全 |
|---|---|---|---|
| GET | SELECT | 是 | 是 |
| POST | INSERT | 否 | 否 |
| PUT | UPDATE | 是 | 否 |
| PATCH | UPDATE | 是 | 否 |
| DELETE | DELETE | 是 | 否 |
传统的 URL
GET /users/query/1 根据用户id查询用户数据
POST /users/save 新增用户
POST /users/update 修改用户信息
POST /users/delete 删除用户信息
RESTful 风格的 URL
GET /users/{id} 根据用户id查询用户数据
POST /users 新增用户
PUT /users 修改用户信息(客户端提供改变后的完整资源)
PATCH /users 修改用户信息(客户端提供改变的属性)
DELETE /users/{id} 删除用户信息
RESTful 设计准则
宾语必须是名词
宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。比如,/articles 这个 URL 就是正确的,而下面的 URL 不是名词,所以都是错误的。
/getAllCars
/createNewCar
/deleteAllRedCars
小驼峰命名
宾语使用全小写名词表示,但有时一个名词无法完全描述清楚时,统一使用小驼峰命名
GET /companyContracts/1
复数 URL
既然 URL 是名词,那么应该使用复数,还是单数? 这没有统一的规定,但是常见的操作是读取一个集合,比如 GET /articles(读取所有文章),这里明显应该是复数。 为了统一起见,建议都使用复数 URL,比如 GET /articles/2 要好于 GET /article/2。
避免多级 URL
常见的情况是,资源需要多级分类,因此很容易写出多级的 URL,比如获取某个作者的某一类文章。
GET /authors/12/categories/2
这种 URL 不利于扩展,语义也不明确,往往要想一会,才能明白含义。 更好的做法是,除了第一级,其他级别都用查询字符串表达。
GET /authors/12?categories=2
下面是另一个例子,查询已发布的文章。你可能会设计成下面的 URL。
GET /articles/published
查询字符串的写法明显更好。
GET /articles?published=true
版本号放入 URL
若有多个 API 版本,应该将 API 的版本号放入 URI
GET /api/v2/authors/1
移动端接口
遵循最小化原则,业务完全相同使用同一个接口,不同则添加/mobile 体现 PC 端和移动端的对应关系
GET /authors/12
GET /mobile/authors/12
Swagger 注释
在 Swagger 中需包含详细注释说明,包括:
- 接口描述
- 请求数据类型(application/x-www-form-urlencoded、application/json 等)
- 请求参数说明、数据类型、是否必须
- 返回参数说明、数据类型
返回结果
API 返回结果应遵循以下格式与字段命名:
{
"code":200, // 状态码以code命名(好多javascript框架并不会获取http状态码,所以包装到body中便于使用)
"result": { // 返回内容以result命名,多条记录使用JSON数组,单条记录使用JSON对象
"id":null, // 数据类型String,空时为null
"name":"张三",
"age":20 , // 数据类型Number, 空时为null,
"imgUrls": ['地址1', '地址2'], //数据类型Array, 空时为null
"photoUrls": null
},
"message":"成功", // 成功或错误消息,以message命名
"success": true // 是否成功:true或false
}
分页列表返回结果:
{
"code":200, // 状态码以code命名(好多javascript框架并不会获取http状态码,所以包装到body中便于使用)
"result": {
"current": 1, // 当前页数以current命名
"pages": 2, // 总页数以pages命名
"records": [{...}, {...}], // 返回列表以records命名,使用JSON数组
"size": 10, // 每页条数以size命名
"total": 12 // 总条数以total命名
},
"message":"成功", // 成功或错误消息,以message命名
"success": true // 是否成功:true或false
}
状态码
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的 HTTP 动词)
- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
- 201 CREATED - [POST/PUT]:用户新建或修改数据成功。
- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
- 204 NO CONTENT - [DELETE]:用户删除数据成功。
- 400 INVALID REQUEST - [POST/PUT]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
- 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
- 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
- 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
- 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
- 422 Unprocesable entity - [POST/PUT] 当创建一个对象时,发生一个验证错误。
- 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
Powered by Waline v2.15.8