Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前后端接口设计规范 #165

Open
mishe opened this issue Aug 7, 2018 · 1 comment
Open

前后端接口设计规范 #165

mishe opened this issue Aug 7, 2018 · 1 comment

Comments

@mishe
Copy link
Owner

mishe commented Aug 7, 2018

前后端接口设计规范

建议采用RESTful 方式来实施。

  • 说明1:采用RestFul方式实施接口通用性强,异构性强。
  • 说明2:对于使用如Dubbo这样的框架,限于java一种语言范围内,在Provider与Consumer两侧共享一个client.jar包的情形,需要另外包装成RESTFul接口以向外发布。但对于使用Spring Cloud这样框架的新开应用,天然具有采用RestFul方式来实施的便利性。

协议

API与用户的通信协议,总是使用HTTPs协议,确保交互数据的传输安全。

域名

应该尽量将API部署在专用域名之下。
https://api.example.com

如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。
https://example.org/api/

api版本控制

应该将API的版本号放入URL。
https://api.example.com/v{n}/
另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

采用多版本并存,增量发布的方式
v{n} n代表版本号,分为整形和浮点型
整形的版本号: 大功能版本发布形式;具有当前版本状态下的所有API接口 ,例如:v1,v2
浮点型:为小版本号,只具备补充api的功能,其他api都默认调用对应大版本号的api 例如:v1.1 v2.2

已经开放出的接口,不允许修改方法签名(外部接口的URL),避免对接口调用方产生影响。接口过时必须加@deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。

API 路径规则

路径又称"终点"(endpoint),表示API的具体网址。
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。

https://api.example.com/v1/products
https://api.example.com/v1/users
https://api.example.com/v1/employees

HTTP请求方式

对于资源的具体操作类型,由HTTP动词表示。
常用的HTTP动词有下面四个(括号里是对应的SQL命令)。
GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
DELETE(DELETE):从服务器删除资源。

下面是一些例子。

GET /product:列出所有商品
POST /product:新建一个商品
GET /product/ID:获取某个指定商品的信息
PUT /product/ID:更新某个指定商品的信息
DELETE /product/ID:删除某个商品
GET /product/ID/purchase :列出某个指定商品的所有投资者
get /product/ID/purchase/ID:获取某个指定商品的指定投资者信息

过滤信息

如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。

下面是一些常见的参数。
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?producy_type=1:指定筛选条件

API 传入参数

参入参数分为4种类型:

地址栏参数
- restful 地址栏参数 /api/v1/product/122 122为产品编号,获取产品为122的信息
- get方式的查询字串 见过滤信息小节
请求body数据
cookie
request header

cookie和header 一般都是用于OAuth认证的2种途径

返回数据

只要api接口成功接到请求,就不能返回200以外的HTTP状态。
为了保障前后端的数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。

接口返回模板:

{
    status:0,
    data:{}||[],
    msg:’’
}

status: 接口的执行的状态

> =0表示成功
<0 表示有异常 
>0 表示接口有部分执行失败

Data 接口的主数据

可以根据实际返回数组或JSON对象

Msg

当status!=0 都应该有错误信息

接口安全

  • 开放接口供外部使用,需要关注接口运行的安全性,比如可以通过使用漏桶和令牌桶等算法来进行接口的限流、通过非对称加密等方式来保护接口数据的安全性、通过使用时间戳加整个url签名的方式来防止重放攻击和进行限流保护。

  • 对外提供的开放接口,需要进行参数有效性校验。不合法入参的接口请求在校验阶段就应该返回了,不至于继续操作后台数据库或其他数据存储。

  • 对外提供的开放接口,需要提供入参保护,包括检查入参有效值的范围、检查入参落在白名单列表范围、批量查询操作的数据量范围等。

api接口文档

后端接口开发中,使用类似于Swagger 、Api2Doc等接口管理工具,定义接口内容包含:接口名称(name),接口地址(url),输入参数(params),返回值(data),错误码(errorCode),错误信息(errorMessage)。

非Restful Api的需求

由于实际业务开展过程中,可能会出现各种的api不是简单的restful 规范能实现的,因此,需要有一些api突破restful规范原则。特别是移动互联网的api设计,更需要有一些特定的api来优化数据请求的交互。

页面级的api

把当前页面中需要用到的所有数据通过一个接口一次性返回全部数据
举例: api/v1/get-home-data 返回首页用到的所有数据

这类API有一个非常不好的地址,只要业务需求变动,这个api就需要跟着变更。

自定义组合api

把当前用户需要在第一时间内容加载的多个接口合并成一个请求发送到服务端,服务端根据请求内容,一次性把所有数据合并返回,相比于页面级api,具备更高的灵活性,同时又能很容易的实现页面级的api功能。

地址:api/v1/batApi

传入参数:
>data:[
{url:'api1',type:'get',data:{...}},
{url:'api2',type:'get',data:{...}},
{url:'api3',type:'get',data:{...}},
{url:'api4',type:'get',data:{...}}
]
返回数据
>{status:0,msg:'',
data:[
    {status:0,msg:'',data:[]},
    {status:-1,msg:'',data:{}},
    {status:1,msg:'',data:{}},
    {status:0,msg:'',data:[]},
]
}

跨域

前后端分离后,接口所在域名和前端展示逻辑代码不在一个域名,但由于浏览器同源策略限制,前端AJAX请求无法获取数据,因此需要来解决跨域问题。
常见的跨越方案有JSONP,CORS, nginx或node代理跨域;jsonp的安全性会降低,nginx或node代理会增加api服务,CORS相对最容易,也比较安全;服务端设置Access-Control-Allow-Origin:*;如果接口需要读取cookie的话,那么前端也需要做一些简单的配置。
java示例:

// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名
response.setHeader("Access-Control-Allow-Credentials", "true"); 
  • 原生ajax代码:
// 前端设置是否带cookie
xhr.withCredentials = true;
  • jQuery ajax
$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    ...
});
  • vue框架
在vue-resource封装的ajax组件中加入以下代码:
Vue.http.options.credentials = true

参考链接
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
https://github.com/thx/RAP/wiki/about_cn

#129
#126

@lxh-015
Copy link

lxh-015 commented Jul 15, 2022

如果需要批量删除指定资源, 有什么好的方法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants