https://github.com/f2e-journey/treasure/blob/master/api.md
随着前后端分离越来越普遍, 后端接口规范也就越来越重要了. 一套良好的接口规范可以提升工作效率, 减少沟通障碍.
通常我们都会采用 REST 方式来提供接口, 使用 JSON 来传输数据.
名词 | 含义 |
---|---|
前端 | Web前端, APP端, 桌面端等一切属于用户界面的这一层 |
后端 | 即服务器端, 指一切属于用户界面之下的这一层 |
前后端接口 | 前端与后端进行数据交互的统称, 也叫做数据接口, 属于一种远程调用, 一般指前端通过HTTP(ajax)请求获取到的数据或者执行的某项操作. 为确保前后端(工程师)的协作沟通, 一般由前端和后端一起来定义接口的规范, 规范的内容一般包含接口的地址, 接口的输入参数和输出的数据格式(结构), 最终由后端来实现这些规范, 为前端提供符合规范的接口 |
[前端]
--------
^
|
|
前后端接口
|
|
--------
[后端]
在开发之前一定要先定义好接口规范, 至于接口应该由前端来定还是后端来定, 这个还得看公司的具体情况, 但一定要让前后端都确认无误, 特别是接口协商要点.
以免出现前后端分离之后最容易出现的扯皮现象. 特别是当你碰到做事不主动(无责任感)的后端, 什么都要前端来催. 比如什么接口又缺了一个字段没有提供啦, 什么又少了一个接口啦, 等等诸如此类. 后端不去熟悉业务, 也不看界面原型和需求, 只管把接口做完, 任务完成就万事大吉了, 每天除了等前端通知哪里要修改, 自己就像没事人一样.
所以说定好接口, 前后端一起来确认好接口是多么的重要, 不然你就等着干着急吧. 当然了, 想一次性完美地将所有接口都定义出来, 有点不太现实, 需要调整的情况在所难免, 所以还是希望后端能够主动一点, 前后端沟通的时候就轻松得多, 大家的效率就都提高了.
由前端(APP端)和后端一起协定接口规范的内容, 确定每一个接口的地址(URL), 输入(request)和输出(response), 必要的时候详细注释每一个字段的含义和数据类型.
具体需要定义哪些接口, 可以按照下面的思路来整理
null
的对应数据类型初始值, 例如对象类型的返回空对象({}
), 数组类型的返回空数组([]
), 其他原始数据类型(string
/number
/boolean
…)也使用对应的默认值result.fieldName
result
为 null
, 可想而知会报错 Uncaught TypeError: Cannot read property 'fieldName' of null
"status": 1
http://a.res.com/path/to/img.png
这就是完整的, 前端直接使用这个 URL/path/to/img.png
这就是部分的, 一般省略域名部分, 前端需要自己拼接后才能使用 'http://a.res.com' + '/path/to/img.png'
1458885313711
, 或者参考 Date.prototype.toJSON 提供 ISO 标准格式(例如需要考虑时区时)2017年1月1日
JavaScript
会发生溢出, 造成得到的数值错误
{"id": 362909601374617692}
前端拿到的值却是: 362909601374617660
所有的接口定义在项目前端静态文件目录的 _mockserver.json
文件中, 启动 puer-mock
服务, 即可使用这些接口获得符合规范的假数据, 也可以查看接口文档.
具体 puer-mock
的详细使用手册和 _mockserver.json
如何配置接口请参考 puer-mock 项目, 或者参考项目中已经配置好的其他接口.
由于接口规范的定义和接口的实际实现是分开的两个部分, 而且涉及到多人协作, 因此在开发过程中可能出现接口规范与实现不同步, 最终造成实际的接口不符合规范的定义, 接口规范就会慢慢失去存在的意义.
为了尽量避免这种问题, 后端在实现接口的过程中应该确保与接口规范保持一致, 一旦出现分歧, 必须同步修改接口规范, 尽可能保持沟通.
接口根路径 - Root Endpoint 推荐为: http://api.yourdomain.com
或者 http://yourdomain.com/api
接口地址即接口的 URL, 定义时使用相对路径(即不用带上域名信息), 建议分模块来定义, 推荐 REST 风格, 例如
GET /user/:id
表示获取用户信息POST /user
表示新增用户向接口传递参数时, 如果是少量参数可以作为 URL query string 追加到接口的 URL 中, 或者作为 Content-Type: application/x-www-form-urlencoded
放在请求体(body
)中(即表单提交的方式)
对于复杂的接口参数(例如嵌套了多层的数据结构), 推荐在 HTTP 请求体(body
)中包含一个 JSON 字符串作为接口的参数, 并设置 Content-Type: application/json; charset=utf-8
.
例如
查询 VIP 用户的接口
POST /users?limit=10 HTTP/1.1
Content-Type: application/json; charset=utf-8
{
"name": "hanmeimei",
"isVip": true
}
返回的响应体类型推荐为 Content-Type: application/json; charset=utf-8
, 返回的数据包含在 HTTP 响应体中, 是一个 JSON Object. 该 Object 可能包含 3 个字段 data
, status
, statusInfo
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"data": {},
"status": 0,
"statusInfo": {
"message": "给用户的提示信息",
"detail": "用于排查错误的详细错误信息"
}
}
字段名 | 字段说明 |
---|---|
data | 业务数据 必须是任意 JSON 数据类型(number/string/boolean/object/array). 推荐始终返回一个 object (即再包一层)以便于扩展字段. 例如: 用户数据应该返回 {"user":{"name":"test"}} , 而不是直接为 {"name":"test"} |
status | 状态码 必须是 >= 0 的 JSON Number 整数.
|
statusInfo | 状态信息 必须是任意 JSON 数据类型. 推荐始终返回一个 object 包含 message 和 detail 字段
|
例如
接口处理成功时接口返回的数据
{
"data": "api result"
"status": 0
}
接口处理失败时接口返回的数据
{
"status": 1,
"statusInfo": {
"message": "服务器正忙",
"detail": {
"exception": "java.util.List"
}
}
}
这样我们就可以非常容易地通过判断 status 来处理数据了
if (!response.status) {
// status 为 0 或者没有 status 字段时表示接口成功返回了数据
console.log(response.data);
} else {
// 失败
console.error(response.status, response.statusInfo);
// 统一由服务端返回给用户的提示信息
alert(response.statusInfo.message);
}
status
字段该如何取值采用前后端分离开发模式的项目越来越多, 前端负责调用后端的接口来展现界面, 如果有界面显示异常, 需要有快速方便的手段来排查线上错误和定位出职责范围
综合了经验总结和行业实践, 最简单有效的手段是制定出一套统一的错误码规范, 协助多方人员来排查出接口的错误
例如
因此我们确定提示信息规范为: 当后端接口调用出错时, 接口提供一个用户可以理解的错误提示, 前端展示给用户错误提示和错误码, 给予用户反馈
对于错误码的规范, 参考行业实践, 大致有两种方案
A101
, B131
具体实践如下
错误码固定长度, 以区间来划分错误类型(例如 HTTP 的状态码)
例如: 10404 表示 HTTP 请求 404 错误, 20000 表示 API 调用失败, 30000 代表业务错误, 31000 表示业务A错误, 32000 表示业务B错误
错误码可不固定长度, 以首字母来划分错误类型, 可扩展性更好, 但实际运作还是需要划分区间
例如: H404 表示 HTTP 请求 404 错误, A100 表示 API 调用失败, B100 表示业务A错误, B200 表示业务B错误
关于错误分类的原则, 我们可以根据发送请求的最终状态来划分
错误码可不固定长度, 整体格式为: 字母+数字
, 字母
作为错误类型, 可扩展性更好, 数字
建议划分区间来细分错误
例如:
A
for API: API 调用失败(请求发送失败)的错误, 例如 A100
表示 URL 非法H
for HTTP, HTTP 异常状态的错误, 例如 H404
表示 HTTP 请求404错误B
for backend or business, 接口调用失败的错误, 例如 B100
业务A错误, B200
业务B错误C
for Client: 客户端错误, 例如 C100
表示解析 JSON 失败${错误码}
) ${HTTP 方法}
${HTTP URL}
${请求参数}
${请求选项}
${请求返回结果}
接口调用出错(H404) GET https://domain.com {foo: bar} {option1: 'test'} {status: 404}
规范实现: weapp-backend-api
GET /contact
获取联系人, POST /contact
新增/修改联系人362909601374617692
, 作为 JSON 数据返回给前端, 前端拿到的值变成了 362909601374617660
{"sex": 1, "sexText": "男"}
{"pic": "https://domain.com/a.png"}
{"createTime": 1543195480357, "createTimeText": "2018年11月26日"}
E-JSON数据传输标准
有范云协作 让项目的协作姿势更有范儿
- 交互阶段说明
- 交互设计师根据产品方的需求对产品进行行为设计和界面设计的阶段,主要产出物为交互设计稿
- 开发工程师需要做的事情是针对产品需求、交互设计稿中的内容进行技术评审,为产品方、交互设计师提供可行技术实现解决方案,对于多种不同解决方案需针对各种解决方案做分析说明,务必准确传达各种方案的优缺点,并根据需求给出建议方案
- 系统设计说明
- 各端开发工程师针对产品需求说明、交互设计稿开始设计系统架构、拆分子系统、划分子系统模块、协调端与端之间的接口规范,这个阶段各端根据实际情况输出若干系统设计说明书等文档
- 除此之外更重要的是输出端与端之间通信的接口规范,而这个规范则可以借助 NEI 平台 来完成
- 编码阶段说明
- 开发工程师根据系统设计阶段的输出,用代码来实现这样的系统,包括技术方案的选型、项目框架的搭建、工具及环境的配置等
- 其中有些工作可以借助于有范云协作提供的自动化工具 NEI-Toolkit 来完成,比如项目的初始结构代码、在 NEI平台 上定义好的接口规范等
- 自测阶段说明
- 各个端的工程师验证自己编写的代码的正确性,按角色不同,测试方式也有所有不同
- 对于前端和移动端工程师来说,主要是需要测试各种可能的值会不会影响界面展示
- 对于服务端工程师来说,主要是测试提供给客户端工程师使用的接口的正确性,对于不同的输入参数是否返回了预期的结果
- 联调阶段说明
- 主要是连测试环境进行测试
- 对于前端和移动端工程师来说,主要是需要将本地容器提供的接口换成测试环境的接口
- 测试阶段说明
- 开发工程师开发完成后提测的过程,是产品上线前的最后环节
- 测试工程师会对接 NEI 平台生成接口测试用例代码并集成到自动化测试平台运行,如果NEI平台的接口定义与实际提测的项目不符则此次提测失败,需由开发对照 NEI 平台检查接口实现情况,所以可以保证 NEI 平台上的接口定义始终与线上保持一致
客户端API请求规范
参数名 说明 imei 国际移动设备身份码 imsi 客户端用户标识 t TIMESTAMP,请求的时间戳 appkey 由服务端颁发的appkey sign md5签名串。为了减轻非法恶意请求,每次来自APP的请求都需要对请求参数进行签名以实现安全认证 lng 手机上获取的经度 lat 手机上获取的纬度 ci 渠道标识,格式为:channelId@应用名平台客户端版本,例如:1001@nzaom_android_1.0,其中1001表示应用宝
GitHub API | 微博API | 淘宝开放平台 API
JSend | JSON API | JSON Schema | JSON-RPC | JWT | OAuth
Type Description Required Keys Optional Keys success All went well, and (usually) some data was returned. status, data fail There was a problem with the data submitted, or some pre-condition of the API call wasn’t satisfied status, data error An error occurred in processing the request, i.e. an exception was thrown status, message code, data
Google JSON Style Guide
最佳实践:更好的设计你的 REST API | RESTful API 设计指南 | Best Practices for Designing a Pragmatic RESTful API | HTTP API Design Guide | The RESTful Cookbook | RESTful API 编写指南
Restlet Studio - Web IDE for API design | Swagger | ReDoc | RAML | API Blueprint