URI
URI规范
- 不要用大写
- 单词间使用下划线’_’
- 不使用动词,资源要使用名词复数形式,如:users、rooms、tickets
- 层级大于等于三层,则使用’?’带参数
1
sers/1/address/2/citys (bad) /citys?users=1&address=2; (good)
避免层级过深的URI
过深的导航容易导致url膨胀,不易维护,如 GET /zoos/1/areas/3/animals/4
,尽量使用查询参数代替路径中的实体导航,如GET /animals?zoo=1&area=3
;
Request
Method
- GET:查询资源
- POST:创建资源
- PUT:全量更新资源(提供改变后的完整资源)
- PATCH:局部更新资源(仅提供改变的属性)
- DELETE:删除资源
下面一些例子
- GET /zoos:列出所有动物园
- POST /zoos:新建一个动物园
- GET /zoos/ID:获取某个指定动物园的信息
- PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
- PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
- DELETE /zoos/ID:删除某个动物园
- GET /zoos/ID/animals:列出某个指定动物园的所有动物
- DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
安全性与幂等性
- 安全性:任意多次对同一资源操作,都不会导致资源的状态变化
- 幂等性:任意次对同一资源操作,对资源的改变是一样的
Method | 安全性 | 幂等性 |
---|---|---|
GET | 是 | 是 |
POST | 否 | 否 |
PUT | 否 | 是 |
PATCH | 否 | 是 |
DELETE | 否 | 是 |
参数
Method
GET
非id的参数使用’?’方式传输/users/1?state=closed
POST、PATCH、PUT、DELETE
非id的参数使用body传输,并且应该encode
过滤
?type=1&state=closed
排序
分页
?size=10&page=1
- size:返回记录数量
- page:第几页
版本控制
三种方案:
- 在uri中加入版本: /v1/room/1
- Accept Header:Accept: v1
- 自定义 Header:X-ProjectName-Media-Type: projectname.v1 (我们使用此方案)
状态码
成功
Code | Method | Describe |
---|---|---|
200 | ALL | 请求成功并返回实体资源 |
201 | POST | 创建资源成功 |
客户端错误
Code | Method | Describe |
---|---|---|
400 | ALL | 参数错误 |
401 | ALL | 用户验证失败(用户名、密码错误等) |
404 | ALL | 资源不存在 |
服务器错误
Code | Method | Describe |
---|---|---|
500 | ALL | 服务器未知错误 |
Response
不要包装:response的body直接就是数据,不要做多余的包装。
错误示例:1
2
3
4{
"success":true,
"data":{"id":1,"name":"xiaotuan"},
}
正确示例:1
{"id":1,"name":"xiaotuan"}
json格式的约定:
- 时间用长整形(毫秒数),客户端自己按需解析(moment.js)
- 不传null字段
分页response
1 | { |
错误处理
- 不要发生了错误但给2xx响应,客户端可能会缓存成功的http请求;
- 正确设置http状态码,不要自定义;
- Response body 提供 1) 错误的代码(日志/问题追查);2) 错误的描述文本(展示给用户)。
1 | { |
对PUT,POST,PATCH的输入的校验也应该返回相应的错误信息,例如:
1 | { |
参考
http://imweb.io/topic/5707561f06f2400432c139a5
https://blog.restcase.com/rest-api-error-codes-101/