RESTful API接口设计规范
RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。
REST(Representational State Transfer)表述性状态转换,REST指的是一组架构约束条件和原则。 如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。
稳定性、接口的跨域性、接口的协议规则、接口的路径规则、接口单一原则、接口过滤和接口组合等诸多因素
一、规范性建议
1. 职责原则
在设计接口时,必须明确接口的职责,即接口类型,接口应解决什么业务问题等
2. 单一性原则
在明确接口职责的条件下,尽量做到接口单一,即一个接口只做一件事,而非两件以上。
3. 协议规范
在设计接口时,应明确接口协议,是采用HTTP协议,HTTPS协议还是FTP协议,要根据具体情况来定。HTTPS=HTTP+SSL,适用于对安全性要求较高的业务情景。HTTP协议,适用一般对安全性要求比较低或没要求的业务情景。FTP协议是一套标准的文件传输协议,用于传输文件,如.txt,.csv等,一般文件传输,采用FTP协议。
4.URI路径规则
由于API获取的是一种资源,所以网址URI中尽量为名词,而非动词;URI中的名词表示资源集合,使用复数形式;不用大写;用中杠-不用下杠_;避免层级过深的URI。
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:删除某个指定动物园的指定动物
应该将API的版本号放入URL。如:
https://api.example.com/v1/
将版本号放在HTTP头信息中,但不如放入URL方便和直观
req.setRequestHeader("Accept", "vnd.example-com.foo+json; version=1.1");
$.ajax({
beforeSend: function (req) {
req.setRequestHeader("Accept", "vnd.example-com.foo+json; version=1.1");
},
type: "GET",
url: "http://http://www.example.com/foo/12",
success: function (data) {
/* code elided */
},
dataType: "json"
});
一般地,域名分为主域名和专有域名,主域名适合API长期不变或变化较少的业务,专有域名是解决具体的专有业务的。
建议将API部署在专有域名下,以此屏蔽消费者对服务提供方的部署细节(可借助于平台的反向代理+路由网关)
https://api.example.com
https://example.com/api/
5.Http请求方式
接口基本访问协议:GET(获取)、POST(新增)、PUT(修改)、DELETE(删除)
GET /zoos:列出所有动物园
GET /zoos/ID:获取某个指定动物园的信息
POST /zoos:新建一个动物园
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
DELETE /zoos/ID:删除某个动物园
6.跨域考虑
在明确域名的情况下,一定要考虑接口是否跨域,以及跨域应采用的技术手段等。
7.适度过滤信息
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。
当记录数比较多时(如 select id,name,age from zoos),应适当添加一些条件对数据进行过滤,如TOP,分页,分组,排序和WHERE条件等
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page_number=2&page_size=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,
GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同
8.返回数据格式
一方面,出于平台标准化的API管理,另一方面,遵循微服务的宽进严出设计理念,建议RESTful采用标准的Json格式。返回结果为统一的json格式。返回数据格式,一般包括三个字段。
失败情况(状态码、错误码和错误描述)
{
"status":0, //状态码 0-表示失败,1-表示成功
"error_code":”2003”,//错误码,一般在设计时定义
"error_des":”身份验证失败”//错误描述,一般在设计时定义
}
成功情况(标识id,数据对象,状态码)
{
"status":1, //状态码 0-表示失败,1-表示成功
"sid":"sh20190111", //Token id
"users": {
"id":"al201901111341", //用户id
"name":"xf98_云雀code"//用户名称
"addr":"福建福州鼓楼区" //地址区域
}
}
{
"status":1, //状态码 0-表示失败,1-表示成功
"sid":"sh20190111", //Token id
"data":{
"id":"al201901111341", //用户id
"name":"xf98_云雀code",//用户名称
"addr":"福建福州鼓楼区",//地址区域
"job":{
"id":"1b434wtert564564sdffeyey", //任务ID
"jobName":"任务名称”
}
}
}
9.安全性原则
接口暴露的考虑,接口并发量的考虑,接口防攻击的考虑,接口跨域的考虑等。
安全性:不会改变资源状态,可以理解为只读的;
幂等性:执行1次和执行N次,对资源状态改变的效果是等价的;
方法 | 安全性 | 幂等性 |
---|---|---|
GET | √ | √ |
POST | × | × |
PUT | × | √ |
DELETE | × | √ |
10.可扩展性原则
在设计接口时,充分考虑接口的可扩展性。
11.定义API界限
任何API,从权限上,可归结为匿名API和非匿名API,前者不需要验证,后者需要验证。
12.定义API返回码
在API设计时,要定好API返回码。随着系统发展,总有一些API失效或者迁移,对失效的API,返回404 not found 或 410 gone;对迁移的API,返回 301 重定向。
常见状态码
1) 200 OK [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)
2) 201 CREATED [POST/PUT/PATCH]:用户新建或修改数据成功
3) 202 Accepted [*]:表示一个请求已经进入后台排队(异步任务)
4) 204 NO CONTENT [DELETE]:用户删除数据成功
5) 400 INVALID REQUEST [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的
6) 401 Unauthorized [*]:表示用户没有权限(令牌、用户名、密码错误)
7) 403 Forbidden [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的
8) 404 NOT FOUND [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的
9) 406 Not Acceptable [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)
10) 410Gone [GET]:用户请求的资源被永久删除,且不会再得到的
11) 422Unprocesable entity [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误
12) 500INTERNAL SERVER ERROR [*]:服务器发生错误,用户将无法判断发出的请求是否成功
13.异步任务
对耗时的异步任务,服务器端接受客户端传递的参数后,应返回创建成功的任务资源,其中包含了任务的执行状态。客户端可以轮训该任务获得最新的执行进度。如果任务的执行状态包括较多信息,可以把“执行状态”抽象成组合资源,客户端查询该状态资源了解任务的执行情况。
二、反规范性建议
存在这样一种业务场景:某个接口需要返回多个api接口组合的结果 ,在类似的业务场景下,所设计的接口,具有一定的反规范性。
请求:
data:[
{url:'api1',type:'get',data:{...}},
{url:'api2',type:'get',data:{...}},
]
响应:
{
status:0,
msg:'',
data:[
{status:1,msg:'',data:[]},
{status:1,msg:'',data:{}}
]
}
三、API扩展事项
1、RESTful API依托PaaS平台治理,需要对API进行认证、授权、参数加密等操作,可考虑在HTTP头部加认证token、调用链指令、状态信息等系列信息。
2、API分层,会有内部API和外部API之分,两种API的设计或有不同。
3、对于API设计的状态选择,建议为无状态、N次幂等,但后续或存在性能优化问题。
4、建议了解下GraphQL