前言
前端也做挺长时间了,对接后台接口五花八门,每每遇上奇葩的对接方式都是一顿吐槽。现在看到一篇认为挺不错的文章,记录下来。
1. Request
| 请求方法 | 说明 | 安全性 | 幂等性 |
|---|---|---|---|
| GET(SELECT) | 从服务器取出资源(一项或多项) | √ | √ |
| POST(CREATE) | 在服务器新建一个资源 | × | × |
| PUT(UPDATE) | 在服务器更新资源(客户端提供改变后的完整资源) | × | √ |
| PATCH(UPDATE) | 在服务器更新资源(客户端提供改变的属性) | × | × |
| DELETE(DELETE) | 从服务器删除资源 | × | √ |
说明
- 安全性 :不会改变资源状态,可以理解为只读的;
- 幂等性 :执行1次和执行N次,对资源状态改变的效果是等价的。
- 查询字段内容过多,统一使用POST方式查询,请求地址增加/query加以区分
- 批量删除,统一使用POST方式,请求地址增加/delete加以区分
由于存在批量删除的情况,而一些网关、代理、防火墙在收到DELETE请求后,会把请求的body直接剥离掉。建议将存在批量删除的接口统一改成POST提交,为了标识是删除操作,在请求路径上增加/delete。
以下对Request详细解说
小场景
在音乐中,有纯音乐、摇滚、民谣...等类型;这些类型可以分类为曲风、乐器、音乐人、心情;而这些类型(曲风、乐器)又可分为吉他、钢琴、小提琴
GET
被用于获取资源。不允许对服务器上资源做任何修改操作。
示例:
* GET /music:列出所有音乐(纯音乐、摇滚、民谣...等类型)
* GET /music/ID:获取某种指定音乐类别的信息(纯音乐这种类型)
* GET /music/ID/instrument:列出某个指定的音乐类别的所有乐器(纯音乐这种类型下的乐器(instrument)类别)
复制代码
POST
常用于创建新资源。
示例:
* POST /music:新建一条音乐
复制代码
PUT
常用于更新资源(传整个实体)。通过请求体携带资源发送给服务器
示例:
* PUT /music/ID:更新某个指定音乐的信息(纯音乐、摇滚、民谣...等类型)(提供该音乐类型的全部信息)
复制代码
PATCH
常用于更新局部资源(传指定属性)。如果 URI 对应的资源不存在,服务端可以创建一个新资源
示例:
* PATCH /music/ID:更新某个指定音乐的信息(纯音乐、摇滚、民谣...等类型)(提供该音乐类型的部分信息)
复制代码
PATCH和PUT的区别
-
概念上
- patch方法用来更新局部资源,这句话我们该如何理解?
- 假设我们有一个UserInfo,里面有userId, userName, userGender等10个字段。可你的编辑功能因为需求,在某个特别的页面里只能修改userName,这时候的更新怎么做?
- 人们通常(为徒省事)把一个包含了修改后userName的完整userInfo对象传给后端,做完整更新。但仔细想想,这种做法感觉有点二,而且真心浪费带宽。
- 于是patch诞生,只传一个userName到指定资源去,表示该请求是一个局部更新,后端仅更新接收到的字段。
- 而put虽然也是更新资源,但要求前端提供的一定是一个完整的资源对象,理论上说,如果你用了put,但却没有提供完整的UserInfo,那么缺了的那些字段应该被清空。
-
如何理解put为幂等,patch为非幂等?
The PATCH Method
The PATCH method requests that a set of changes described in the
request entity be applied to the resource identified by the Request-
URI. The set of changes is represented in a format called a "patch
document" identified by a media type. If the Request-URI does not
point to an existing resource, the server MAY create a new resource,
depending on the patch document type (whether it can logically modify a null resource) and permissions, etc.其中有很重要一句说明,如果 URI 对应的资源不存在,服务端可以创建一个新资源。
DELETE
删除资源
示例:
* DELETE /music/ID/instrument/ID:删除某个指定音乐类别的指定乐器(纯音乐这种类型下的乐器(instrument)类别下的某一种乐器)
复制代码
2. Response
HTTP状态码 -- STATUS
| 状态码 | 说明 |
|---|---|
| 200 OK | 服务器成功返回请求的数据 |
| 201 CREATED | 新建或修改数据成功 |
| 202 Accepted | 表示一个请求已经进入后台排队(异步任务) |
| 204 NO CONTENT | 删除数据成功 |
| 400 INVALID REQUEST | 请求有错误,服务器没有进行新建或修改数据的操作(幂等操作) |
| 401 Unauthorized | 没有权限(令牌、用户名、密码错误) |
| 403 Forbidden | 得到授权(与401错误相对),但是访问是被禁止的 |
| 404 NOT FOUND | 请求记录不存在,服务器没有进行操作(幂等操作) |
| 406 Not Acceptable | 请求的格式不符合(比如用户请求JSON格式,但是只有XML格式) |
| 500 INTERNAL SERVER ERROR | 服务器发生错误,无法判断发出的请求是否成功 |
CODE
| 状态码 | 说明 |
|---|---|
| 20000 | success |
| 4XXXX | Client error |
| 40001 | Parameter cannot be empty(参数不可为空) |
| 40002 | Please check the parameter constraints(The parameter is not of the expected type) 参数约束请检查(参数不是期望的类型) |
| 5XXXX | Server error |
| 50001 | invalid access token |
| 50002 | already login in other place |
| 50003 | access token expired |
| 50004 | invalid user (user not exist) |
| 50005 | username or password is incorrect |
格式
- 前后端交互字段全部使用小驼峰方式
- 前后端传输字段需要符合驼峰命名:userName
- 后台返回数据字段需都在data里,不得在data之外;除与前端商定过
- 后台返回值为空时,需返回相对应的键名如:{listData: null} (键值为空时值null)
{
"code": "20000", // 见上述表格(CODE)
"status": "200", // 见上述表格(STATUS)
"data": []/{}, // 多条记录使用JSON数组,单条记录使用JSON对象
"message": [] // 状态为error或fail时,对应的错误信息
}
复制代码
- 为什么要使用code和status,使用一个记录不是可以?
- 讲解:
- 而code是后端手动根据情况而制定的编码,方便前端提示客户端
- 因为status主要记录的是HTTP响应码,好多javascript框架并不会获取http状态码,所以包装到body中便于使用;
- 作用:
- 前端根据code在请求的拦截器做处理,若code !== "20000",则将message作为错误信息提示客户端;在请求拦截器被拦截到错误,也不会继续走该页面上的逻辑处理
- code === "20000"的情况下,客户端的请求将通过拦截器走到页面的逻辑处理,这时可以将status来作为该请求在页面上的相应提示与逻辑判断
3. 其他
排序
使用数组传递排序字段,-表示降序,无任何标识表示升序:
* sorts: ['-age', 'name']
复制代码
时间传递
日期和时间戳如果没有适当和一致地处理,可能是一个真正的头痛。建议使用UTC或GMT时间存储,处理,缓存等时间戳或者使用统一格式化的时间字符串”yyyy-MM-dd HH:mm:ss”