白话RESTful API

1,424 阅读7分钟

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设计

  1. 格式规范

根据RFC3986定义,URL是大小写敏感的。所以为了避免歧义,尽量使用小写字母。

RESTful API 应具备良好的可读性,当url中某一个片段(segment)由多个单词组成时,建议使用 - 来隔断单词,而不是使用“ _”。

/api/featured-post/		# GOOD
/api/featured_post/		# WRONG
  1. 协议

提供给用户的API,尽量使用HTTPs协议。使用HTTPs协议还是HTTP协议本身和RESTful API并无关系,但是这对于提高网站的安全性很重要

  1. 版本控制
  • 应该将API的版本号放入URL:api.example.com/v1/
  • 另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。
  1. 域名

应该尽量将API部署在专用域名之下

https://api.example.com
  1. URL中名词应该使用复数

所用的名词往往和数据库的表名对应,而数据库的表是一组记录的集合,因此URL中的名词即表示一组资源的集合,故URI中的名词要使用复数

  1. URL不能使用动词

在RESTful架构中,每个url代表一种资源,所以url中不能有动词,只能有名词

  1. 正确使用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	# 删除指定学校的指定学生
  1. 状态码

服务器向用户返回的状态码和提示信息

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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  1. 合理使用查询参数

参数规范类似下面

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

参考资料: