概述
2000 年,是Roy Thomas Fielding博士于2000年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。表现层状态转换是根基于超文本传输协议HTTP之上而确定的一组约束和属性,是一种设计提供万维网络服务的软件构建风格。
他是一种风格。而不是规范。
简单理解:URL 定位资源,HTTP 动词(get post put patch delete)描述操作。
要点概述
- 协议- API与用户的通信协议,总是使用HTTPs协议
- 域名- 应该尽量将API部署在专用域名之下。
- 版本- 应该将API的版本号放入URL。
- 路径- 在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数
- HTTP动词- 对于资源的具体操作类型,由HTTP动词表示。
- 过滤信息- 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。例如:/path?limit=10:指定返回记录的数量
- 状态码 -服务器向用户返回的状态码和提示信息。
- 错误处理-如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
{
error: "Invalid API key"
}
- 返回结果
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
- Hypermedia API -RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么
资源路径
RESTful Api 是依照资源为中心,每个url 代表一个资源,因此url 中不能有动词要有名词,形容词也可以使用但是要少用,不论资源是单数还是复数,API 中的表示资源的名词要用复数。此外,命名名词的时候,要依照字母数字下划线区分多个单词,这样设计,是为了和 json对象和属性命名方案保持一致。
【GET】 /v1/tags/{tag_id}
【POST】 /v1/users/{user_id}/roles/{role_id} // 添加用户的角色
当资源变化难依用标准的 restful api 命名的时候,可以考虑用一些特殊的单词 actions 命名
/{resources}/{resource_id}/actions/{action}
【PUT】 /v1/users/{user_id}/password/actions/modify // 密码修改
请求方式
可以通过 get post put patch delete 方式对服务端的资源进行操作。
- GET:用于查询资源
- POST:用于创建资源
- PUT:用于更新服务端的资源的全部信息
- PATCH:用于更新服务端的资源的部分信息
- DELETE:用于删除服务端的资源。
查询参数
restful api 应该提供参数来过滤查询结果。
GET】 /{version}/{resources}/{resource_id}?offset=0&limit=20&orderby={field} [asc|desc]
状态码
使用合适的状态码很重要,不要所有的都返回200或者随便乱用。
HTTP 状态码就是一个三位数,分成五个类别。
1xx:相关信息
2xx:操作成功
3xx:重定向
4xx:客户端错误
5xx:服务器错误
HTTP 状态码-维基百科
问题: 当需要自定义的状态码又不属于那五个类别该怎么办??
异常响应
当出现非2xx http状态码的时,应采用全局的异常机构响应信息
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"code": "INVALID_ARGUMENT",
"message": "{error message}",
"cause": "{cause message}",
"request_id": "01234567-89ab-cdef-0123-456789abcdef",
"host_id": "{server identity}",
"server_time": "2014-01-01T12:00:00Z"
}
请求参数
在设计api 的时候,要对请求参数进行限制说明
【GET】 /v1/users/batch?user_ids=1001,1002 // 批量查询用户信息
参数说明
- user_ids: 用户ID串,最多允许 20 个。
---------------------------++++--------------------------------
【POST】 /v1/users // 创建用户信息
请求内容
{
"username": "jack ma", // 必填, 用户名称, max 10
"realname": "马云", // 必填, 用户名称, max 10
"password": "123456", // 必填, 用户密码, max 32
"email": "[email protected]", // 选填, 电子邮箱, max 32
"weixin": "alibaba", // 选填,微信账号, max 32
"sex": 1 // 必填, 用户性别[1-男 2-女 99-未知]
}
响应参数
服务端返回结果如下:
【GET】 /{version}/{resources}/{resource_id} // 返回单个资源对象
【GET】 /{version}/{resources} // 返回资源对象的列表
【POST】 /{version}/{resources} // 返回新生成的资源对象
【PUT】 /{version}/{resources}/{resource_id} // 返回完整的资源对象
【PATCH】 /{version}/{resources}/{resource_id} // 返回完整的资源对象
【DELETE】 /{version}/{resources}/{resource_id} // 状态码 200,返回完整的资源对象。
// 状态码 204,返回一个空文档
怎么理解 RESTful API 的幂等性
HTTP 幂等方法 : 是指不论调用多少次都不会返回不同的结果的 HTTP方法。
功能 | URL | HTTP Method | 幂等性 |
---|---|---|---|
获取一组数据列表 | /path/records | GET | 幂等 |
根据 ID 获取某笔数据 | /path/records/{recordID} | GET | 幂等 |
新建数据 | /path/records | POST | 非幂等 |
完整更新数据 | /path/records/{recordID} | PUT | 幂等 |
部分更新数据 | /path/records/{recordID} | PATCH | 非幂等 |
删除数据 | /path/records/{recordID} | DELETE | 幂等 |
跨域访问预请求 | /path/records/{recordID} | DELETE |
内容传输格式
RESTful 没有定义 Body 中内容传输的格式,有另外的规范来描述怎么设计 Body 的数据结构。
JSON 文档结构
在顶级节点使用 data、errors、meta,来描述数据、错误信息、元信息,注意 data 和 errors 应该互斥,不能再一个文档中同时存在,meta 在项目实际上用的很少,只有特别情况才需要用到,比如返回服务器的一些信息。
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page[offset]=2",
"last": "http://example.com/articles?page[offset]=10"
},
"data": [
{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"relationships": {},
"links": {
"self": "http://example.com/articles/1"
}
}
],
"included": [],
"meta": {
"version": "1.0.0",
"copyright": "Copyright 2015 Example Corp."
}
}
MIME 类型
JSON API 数据格式已经被 IANA 机构接受了注册,因此必须使用 application/vnd.api+json
类型。客户端请求头中 Content-Type 应该为 application/vnd.api+json
,并且在 Accept 中也必须包含 application/vnd.api+json
。如果指定错误服务器应该返回 415
或 406
状态码。
data 属性
{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"relationships": {},
"links": {
"self": "http://example.com/articles/1"
}
}
- id: 显而易见为唯一标识,可以为数字也可以为hash字符串,取决于后端实现
- type: 描述数据的类型,可以对应为数据模型的类名
- attributes: 代表资源的具体数据
- relationships、links: 为可选属性,用来放置关联数据和资源地址等数据
errors 属性
{
"errors": [
{
"code": 10011,
"title": "Name can't be null"
},
{
"code": 10011,
"title": "Content can't be null",
"detail": ""
}
]
}
参考:
RESRful Api-维基百科
RESTful API 设计指南
RESTful API 最佳实践
通俗理解 RESTful api
json api 中文版
google Json风格指南
HTTP 状态码-维基百科
https://developer.github.com/v3/apps/permissions/
https://www.restapitutorial.com/