本人所在公司为外包公司,先后端人员没有固定的组合,都是跟着项目走的,因而全部的后端/前端开发人员交流不顺畅,每一个人对接口的理解不同,致使了在开发过程当中接口联调须要耗费大量时间。团队内部开会讨论接口规范化的问题,做为前端人员,我提出了本身的见解,在此供你们参考。javascript
由于每一个人对本身使用语言有不一样的理解、HTTP协议熟悉程度不一样、思惟逻辑、开发经验不同。对接口规范有想法的人应该提出本身的观点,给出本身的理由。让别人去评价,讨论出一套统一的规则,最终统一成一个内部的标准。 造成统一标准后由相关人员写出示例。例如前端要对GET请求针对jQuery.ajax
、fetch
、axios
等请求库给出示例代码。之后直接参照示例代码进行开发。html
因为每一个项目在定义接口时有许多不一样的方式,我根据以往的经验,从请求方法、请求头、请求体、响应状态码、响应体等几个方面对接口的规范说说本身的见解。前端
咱们不一样的项目使用的请求方式大概有两种:java
若是使用前者,POST的URL中应该指明要执行的动做,然后者不须要指定。ios
POST /api/user/add HTTP/1.1
POST /api/user/set HTTP/1.1
POST /api/user/delete HTTP/1.1
# 这里例子中约定PUT是新增,POST是修改 POST /api/user HTTP/1.1 PUT /api/user HTTP/1.1 DELETE /api/user HTTP/1.1 复制代码
至于使用前者仍是后者,我更倾向于前者。 若是使用后者时,什么状况下使用POST、什么状况下使用PUT,搜索到了到了一些资料,但看不懂。git
接口URL应该见名知意,有必定的规律。 这里我不太懂,就不作过多赘述。github
前端请求中不该该有undefined
,由于后端不支持(json也不支持)该数据类型。 若是Content-Type
为multipart/form-data
,前端不该该传null,由于会被转化成字符串,后端不能判断出这是用户输入仍是null类型。ajax
每一个项目应该约定请求时下面这些数据表明什么意思json
GET请求应该读取数据,不该该产生任何的“反作用”操做。 这里要注意一点浏览器对URL长度是有限制的,若是查询的URL长度过长会引发不可预期的后果。能够采用POST/PUT进行查询。axios
GET请求的参数应该放在请求的URL中而不该该放在请求体中。 例以下面是一个标准的这个GET请求(不相关HTTP头字段已剔除)
GET /api/user?userId=12345 HTTP/1.1
Host: http://www.example.com
复制代码
这三种请求方法传参数格式都相同,下面以POST为例。 POST类型使用的方式很是多样,见识过各类各样奇葩的方式,也是耽误时间最长的,严重影响开发进度。这里只讨论我认为标准的方式。
POST请求用于新增、修改或删除数据,少数状况下用于查询数据。
POST请求的参数必须放在请求体中。 而POST的请求方式有四种方式:
这几种方式经过HTTP头中的Content-Type
头字段进行控制。
multipart/form-data
咱们如今使用的最多的是multipart/form-data
。
POST /api/user/set HTTP/1.1
Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0
------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userName" 张三 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userId" 123456 ------WebKitFormBoundary2KbanAZwv0mKceX0-- 复制代码
这种方式不适合复杂数据类型的传递,例若有个接口须要同时修改多个用户:
const userList = [
{
userID: 123,
userName: '张三',
isAdmin: true,
}, {
userID: 456,
userName: '李四',
isAdmin: false,
},
];
复制代码
那么在POST请求时只能这么作
POST /api/userlist/set HTTP/1.1
Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0
------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userID" 123,456 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userName" 张三,李四 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="isAdmin" 1,0 ------WebKitFormBoundary2KbanAZwv0mKceX0-- 复制代码
更重要的是这种方式不支持数据类型,传入的全部格式的数据都会转成字符串类型。后端常常要使用1表示true,须要将数组或对象拆分开。
application/json
这是我推荐使用的方式,有效的弥补了multipart/form-data
的缺陷。 但不知什么缘由如今咱们团队基本不使用这种方式。 application/json
也有一个缺陷就是不支持上传文件(有特殊的方法这里也不建议使用),想上传文件仍是使用multipart/form-data
。
下面是请求示例
POST /user HTTP/1.1
Host: http://www.example.com
Content-Type: application/json;charset=utf-8
[{"userID":123,"userName":"张三","isAdmin":true},{"userID":456,"userName":"李四","isAdmin":false}]
复制代码
不知道服务器对于不一样的处理会返回什么样的状态码,这里不作讨论。 咱们会返回一个逻辑状态码code
与提示信息msg
,响应体像下面这样。
{"code":200,"msg":"处理成功!","data":{}}
复制代码
在此基础上增长一些限制:
易于扩展,例如当前接口是用户列表页,data使用数组。v2版本接口加入了分页查询,就必须使data变为对象类型了。
复杂类型包括数组与对象。 为了方便阅读,这里将json字符串转化为了JS对象。
const resBody = {
code: 200,
msg: '处理成功',
data: {
list: [
{
userID: 123,
userName: '张三',
},
],
},
};
复制代码
若是没有数据的时候返回
const resBody = {
code: 200,
msg: '处理成功',
data: {
list: null,
},
};
复制代码
这样前端在遍历list时,null会致使代码出错,应该始终保证该字段的数据类型不变,正确返回方式以下。
const resBody = {
code: 200,
msg: '处理成功',
data: {
list: [],
},
};
复制代码
若是你有其余补充或纠正,欢迎👏评论。