restful接口设计规范

一、概述

本文学习 RESTful API 设计相关的一些原则和规范。

少量的API在使用时不知不觉,但是当后续API不断增加了,需求变动也会导致API版本的变化。主要是为了可以进行规范化开发,并非是只能使用该规范,其他做法亦可,只是作为前人大佬已经在实践中进行总结整理。学习好的编程设计规范总是便捷有利的。

二、常见规范

1、协议和域名

API通讯使用http协议,如果能使用https尽量使用https。

尽量使用独立域名,

https://ladfeng.top

http://ladfeng.top

如果不能使用可以以api 打头区分访问

https://ladfeng.top/api

2、版本变化

常见的三种版本方式:

  1. 在uri中放版本信息:GET /v1/users/1
  2. Accept Header:Accept: application/json+v1
  3. 自定义 Header:X-Api-Version: 1

推荐用第一种,虽然没有那么优雅,最明显最方便。

3、URI资源

3、URI资源

(1)URI概念

URI 表示资源,资源一般对应服务器端领域模型中的实体类。
URI规范

  • 不用大写;
  • 用中杠-而不用下杠_;
  • 参数列表要encode;
  • URI中的名词表示资源集合,使用复数形式;
  • 避免层级过深
  • 带上版本号
(2)资源路径

资源集合:

所有动物园

/zoos/    

id为1的动物园内的所有动物

/zoos/1/animals

单个资源:

比如:id为1的动物园

/zoos/1      

id为1,2,3的动物园

/zoos/1;2;3   

层级过深资源:

过深的导航容易导致url膨胀,不易维护,如 GET /zoos/1/areas/3/animals/4,尽量使用查询参数代替路径中的实体导航,如GET /animals?zoo=1&area=3;

4、操作类型

对于资源的具体操作类型,由HTTP动词表示。

常用的HTTP动词有下面五个。

HTTP动作含义对应的SQL操作
GET从服务器取出资源(一项或多项)SELECT
POST在服务器新建一个资源。CREATE
PUT在服务器更新资源(客户端提供改变后的完整资源)UPDATE
PATCH在服务器更新资源(客户端提供改变的属性)UPDATE
DELETE从服务器删除资源。DELETE
HEAD获取资源的元数据。
OPTIONS获取信息,关于资源的哪些属性是客户端可以改变的。

示例:

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:删除某个指定动物园的指定动物

5、条件过滤

记录数量很多,不能全返回,需要对数据进行过滤。API应该提供参数,过滤返回结果。

下面是一些常见的参数(分页条件、查询条件)

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

参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的。

6、状态码

(1)常规状态码

常规的状态主要是参考 HTTP 状态码。

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

HTTP状态码

(2)业务类状态码

系统较多的时候,将系统码也带上,使用数字的定义也可以参考HTTP进行设计。

业务系统码+四位数字

具体的可以根据需求来。

(3)错误与异常

发生错误或异常时:

  1. 不响应2xx开头的状态码,客户端可能会缓存成功的http请求;

  2. 正确设置http状态码,遵循HTTP协议规范;

  3. Response body 需要提供的信息

    1. 错误的代码,方便定位日志,排查问题;

    2. 直接正面的描述错误的文本。

如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。

状态码场景
400参数校验失败
401未验证的用户,未登录
403无权限
404资源不存在
500非业务类异常

业务类异常,一般自定义Exception,见词知义。

常规异常:

{
    "status":"failed",
    "code":400"error": "参数xxx校验失败"
}

业务类异常:系统名为ABCD

{
    "status":"failed",
    "code":ABCD2001"error": "XXX数据已经过期。"

}
(4)正常返回

正常返回,减少数据层级。

判断操作成功失败的标记 和操作的单个数据

{
    "success": true,
    "code": 200"msg": "操作成功""data": {
    "id":"1",
    "name":"zhangxiaocai"
}
}

msg可选。

分页查询

{
    "paging":{"limit":10,"offset":0,"total":119},
    "data":[{},{},{}...]
}

操作与响应

HTTP操作响应格式
GET状态标记+集合、单个对象
POST状态标记+新增成功的对象
PUT/PATCH状态标记+更新成功的对象
DELETE状态标记
(5)异步任务

对耗时的异步任务,服务器端接受客户端传递的参数后,应返回创建成功的任务资源,其中包含了任务的执行状态。客户端可以轮训该任务获得最新的执行进度。

比如常见信息:

任务ID,任务执行状态,发起人。
请求:

GET /task/3    

返回:

{
    "taskId":3,
    "createBy":"Anonymous",
    "status":"success"
}

{
    "taskId":3,
    "createBy":"Anonymous",
    "status":"running"
}

批量请求:

POST /batchTasks/1;2;3;

批量返回:

[{
    "taskId":3,
    "createBy":"Anonymous",
    "status":"success"
},
 {},{}...]

[{"from":0,"to":1,"info":"Runing 50 %"},{},{}...]

如果任务的执行状态包括较多信息,可以把“执行状态”抽象成组合资源,客户端查询该状态资源了解任务的执行情况。

提交:

GET /task/3/status

返回:

{
    "progress":"50%",
    "total":18,
    "success":8,
    "fail":1
}

7、Hypermedia API

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

比如,当用户向api.doname.com的根目录发出请求,会得到这样一个文档。

{"link": {
"rel":   "collection https://www.example.com/zoos",
"href":  "https://api.example.com/zoos",
"title": "List of zoos",
"type":  "application/vnd.yourformat+json"
}}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

{
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}

从上面可以看到,如果想获取当前用户的信息,应该去访问api.github.com/user,然后就得到了下面结果。

{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}

上面代码表示,服务器给出了提示信息,以及文档的网址。

8、数据格式

JSON 或 XML 按要求使用即可。

欢迎点赞关注哦!
也欢迎到访我的博客!小小的博客传送门!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兴趣使然的小小

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值