1. 引言
在理解RESTful API之前,我们先了解下什么是REST。整个文章主要以HTTP来举列说明
1.1 REST含义
REST:全称是 Resource Representational State Transfer,或者说表现层状态转移。它是一种互联网应用程序的API设计理念(可以用URL定位资源,用HTTP动词描述操作),是一种软件架构风格、设计风格,而不是标准。
Resource(资源):就是网络上的一个实体,或者说是网络上的一个具体信息。他可能是一段文本,一张图片,一个视频或者一种服务,我们用一个 URI (唯一资源标示符)来唯一指向特定的某个资源
Representational(表现层):资源是一种信息实体,可以有多种表现形式,比如JSON,XML等,一个资源的具体表现形式,应该在 HTTP 请求的头信息中,使用 Accept 和 Content-Type 字段来指定.
State Transfer(状态转化):用户访问网站实际上是一个客户端和服务器之间的互动过程,这个过程中双方不断的建立连接进行通信,势必会涉及到数据和状态的变化

1.2 REST的6个基本原则
- C-S架构
数据的存储在Server端,Client端只需使用就行。两端单独开发,互不干扰
- 无状态
http请求本身就是无状态的,基于C-S架构,客户端的每一次请求带有充分的信息能够让服务端识别。服务端能够根据请求的各种参数,无需保存客户端的状态,将响应正确返回给客户端。
- 统一的接口
REST架构的核心内容,统一的接口可以让客户端只需要关注实现接口就可以,接口的可读性加强,使用人员方便调用。
REST接口约束定义为:通过uri标出你要操作的资源,通过请求动作(http method)标识要执行的操作,通过返回的状态码来表示这次请求的执行结果。
- 一致的数据格式
服务端返回的数据格式要么是XML,要么是Json(获取数据),或者直接返回状态码
- 可缓存
在万维网上,客户端可以缓存页面的响应内容。因此响应都应隐式或显式的定义为可缓存的,若不可缓存则要避免客户端在多次请求后用旧数据或脏数据来响应。
- 按需编码、可定制代码
REST允许客户端通过下载并执行一些来自于服务端的脚本程序,来对客户端功能进行扩展。这样可以简化客户端功能的开发,比如常见的移动端webview,web小游戏等。【该原则是可选约束】

2. 什么是RESTful架构/风格
一个架构如果符合REST原则,就称它为RESTful架构或者RESTful风格。
REST设计准则中,只有按需编码为可选项。如果违反了其他任意一项准则,严格意思上不能称之为RESTful架构。
RESTFul架构总结来说就是:
用URI来定位具体的资源。
用HTTP请求的Content-Type字段来描述资源的表现形式。
用HTTP的4个动词(GET、POST、PUT、PATCH)来描述对资源的具体操作。
3. 什么是RESTful API
可以理解为基于REST构建的API。是RESTFul架构的具体的一种实现 【RESTful是REST的形容词】
RESTful API最大好处概要来说就是:在别人使用你提供得API接口时,即使用户不查看文档,也知道下一步应该做什么
4. 为什么使用RESTful API
“远古时期”前端后端是融和在一起的,比如之前的PHP,JSP等,但是随着近年来移动互联网的发展,各种客户端出不穷:Web,IOS,Android。因此需要一种机制使得各种客户端能够和服务端进行通讯,这就使得RESTful的架构流行起来。RESTful架构如下:

5. 如何进行RESTful API设计
- 格式规范
根据RFC3986定义,URL是大小写敏感的。所以为了避免歧义,尽量使用小写字母。
RESTful API 应具备良好的可读性,当url中某一个片段(segment)由多个单词组成时,建议使用 - 来隔断单词,而不是使用“ _”。
/api/featured-post/ # GOOD
/api/featured_post/ # WRONG
- 协议
提供给用户的API,尽量使用HTTPs协议。使用HTTPs协议还是HTTP协议本身和RESTful API并无关系,但是这对于提高网站的安全性很重要
- 版本控制
- 应该将API的版本号放入URL:api.example.com/v1/
- 另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。
- 域名
应该尽量将API部署在专用域名之下
https://api.example.com
- URL中名词应该使用复数
所用的名词往往和数据库的表名对应,而数据库的表是一组记录的集合,因此URL中的名词即表示一组资源的集合,故URI中的名词要使用复数
- URL不能使用动词
在RESTful架构中,每个url代表一种资源,所以url中不能有动词,只能有名词
- 正确使用HTTP动词
GET:从服务器获取资源
POST:在服务器新建一个资源
PUT:在服务器更新资源(客户端提供改变后的完整资源)
PATCH:在服务器更新资源(客户端提供改变的属性)
DELETE:从服务器中删除资源
GET https://api.example.com/v1/schools # 列出所有学校
POST https://api.example.com/v1/schools # 新建一个学校
GET https://api.example.com/v1/schools/ID # 列出指定学校的信息
DELETE https://api.example.com/v1/schools/ID # 删除指定学校
GET https://api.example.com/v1/schools/ID/students # 列出指定学校的所有学生
DELETE https://api.example.com/v1/schools/ID/students/ID # 删除指定学校的指定学生
- 状态码
服务器向用户返回的状态码和提示信息
1xx: 请求相关信息
2xx: 操作成功
3xx: 重定向
4xx: 客户端错误
5xx: 服务端错误
常见的如下:
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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
- 合理使用查询参数
参数规范类似下面
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
- 错误处理
如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
{
error: "Invalid API key"
}
6. 总结
RESTful是一种API设计风格,并不是一种强制规范和标准,它的特点在于请求和响应都简洁清晰,可读性强。
主要关注几点:
无状态
请求URL = 动作(GET/POST/PUT/DELETE)+ 资源
响应使用精确的状态码和JSON格式数据
使用反列和正列参考:
💣💣💣#错误的方式
http://example.com/api/getallUsers //GET 获取所有用户
http://example.com/api/getuser/1 //GET 获取标识为1用户信息
http://example.com/api/user/delete/1 //GET/POST 删除标识为1用户信息
http://example.com/api/updateUser/1 //POST 更新标识为1用户信息
http://example.com/api/User/add //POST添加新的用户
👏👏👏# 规范后的RESTful风格的url,形式固定,可读性强,根据users名词和http动词就可以操作这些资源。
http://example.com/api/users //GET 获取所有用户信息
http://example.com/api/users/1 //GET 获取标识为1用户信息
http://example.com/api/users/1 //DELETE 删除标识为1用户信息
http://example.com/api/users/1 //Patch 更新标识为1用户部分信息,包含在div中
http://example.com/api/users //POST 添加新的用户
参考资料: