如何理解RESTful API
RESTful API 的定义?
在 URL 中使用名词?
http://xxx.com/users
?
使用 HTTP Methods 表示动作?
GET、POST、DELETE、PUT
?
制定 HTTP Code 表明响应状态?
200、302、400、500
?
很多情况下,我们基本都是根据 URL 中所使用的名词、HTTP 不同的请求方式及 HTTP 的状态码来决定一个 API 是否符合 RESTful 的规范
如果一个 API 的 URL 中使用特定名词(例
user
,search
,product
)、特定的 HTTP 请求方式(GET
=>表示获取指定内容、POST
=>提交一份表单、DELETE
=>删除相关内容)和指定的 HTTP 状态码(200
=>请求成功、302
=>资源复用、400
=>客户端异常、500
=>服务端异常),诸如此类,我们就说明该 API 是一个标准的RESTful API
。确实是这样吗?
REST 代表了什么?
REST => (Representational State Transfer)
,即表现层状态转换。
- REST 本质上是一种
软件架构风格
,目的是为了指导万维网及Web应用
的架构设计和开发。
REST 核心内容
- REST 架构风格的核心内容主要包含以下六个方面的约束:
1.客户端 / 服务端(Client / Server)
- 该约束多表现为客户端与服务端分离的应用,即我们常说的前后端分离模式。
- 该模式下客户端(不单指浏览器)只需要关注用户 UI 和交互设计,服务端则只需要关注业务逻辑的具体实现。
2.无状态(StateLess)
- REST 的规定请求一定是无状态的,即当前的请求不能依赖历史请求在服务端生成的特定上下文环境。
- 每个请求应该包含为该请求完成所需的全部信息,好处是简化了服务端实现,有利于服务端更轻松的进行横向扩展,不用考虑状态的处理
3.缓存(Cache)
- 缓存存在的主旨是为了提高网络资源使用效率
- 可在响应中包含特定标记,以表明该响应内容是否需要被缓存方便资源利用
4.统一接口(Uniform Interface)
共包含四个行为:请求中的资源标识 (Resource Identification in Requests)、自描述信息 (Self-description Message)、基于表现的资源操作 (Resource Manipulation Through Representations)、超媒体应用状态请求 (HyperMedia as the Engine of Application State)。
- 请求中的资源标识 :指接口中引用的资源需要以 URI 的形式识别,以表示对某个资源的引用。例`http://xxx.com/posts/13`,用以表明`文章栏目`下标识为`13`的资源
- 不同的资源会以各式各样的形式表现于不同的端内,如上所述,在客户端内它可能会以
HTML
方式展示其相关信息、也可以存储为JSON
,或者被组织成某些个多媒体格式内容(例如 png、mp4 等)。
- 不同的资源会以各式各样的形式表现于不同的端内,如上所述,在客户端内它可能会以
- 自描述信息 :API 会在相应的响应中,返回其表现形式所对应的数据,以及客户端需要如何处理这些数据的`元数据`,比如媒体类型信息、文件类型信息等。
- 基于表现的资源操作 :当客户端持有某种资源的表现形式时,其能够结合与资源或该表现形式相关的元数据,进而改变资源的当前状态。
- 例如,在对应的文章详情内容的 HTML 中我们可以通过
提交一个用户评论的表单内容
这种方式,来更新其文章下的评论内容,这就是对资源状态的一种改变。
- 例如,在对应的文章详情内容的 HTML 中我们可以通过
- 超媒体应用状态请求 :REST 架构风格下的客户端,应该可以使用由服务端提供的链接来动态地发现它所需要的其他可用资源。
例如,用户在访问 URI 为
/posts/13
下的文章时,服务器端应该要返回与标识符 ID13
有关的相关文章 HTML 数据。除此之外,在该数据下,应当还包含在当前状态下,客户端可以继续访问的其他资源链接,例如文章下的
/posts/13/star
、/posts/13/reader
。在此基础上,通过点击访问对应的链接,应用程序都能够以合法的状态完成一次转移。注 :所有合法可用的状态转移路径,均由服务端动态提供。
在该情况下,HTML、可交互图片、视频等都被归纳为超媒体,它们会作为资源的某种表现形式而存在。
用户可以与这些表现形式进行交互,例如通过
提交表单
内容去驱动
应用程序的状态
不断变化。代码示例:
// 成熟模型的基本内容
GET 请求 => http://xxx.com/posts/25
响应 => {
"postId": 25,
"author": "Alan",
"resource":{
"stars": "/posts/25/stars",
"reader": "/posts/25/reader"
}
}
5.分层系统(Layered System)
- 分层系统指的是,客户端与末端服务端并不需要直接相连,两者中间可以夹杂存在若干的其他节点,目前是为了实现负载均衡、流量管控等。
6.按需代码【可选】(Code On Demand)
该表现是属于可选项,它实际上并不需要像前几者那样去强制性约束并实施。
该项内容意味着,客户端可以向服务端按需请求相关代码,服务器根据客户端情况发送相关可执行代码,用以增强客户端能力。
- 例如:当应用使用了客户端无法默认识别的自定义媒体类型时,服务器端可以通过动态发送代码的方式来为客户端提供解析该媒体类型的能力。
REST 架构风格下的 Web API 等级
在 2008 年,美国程序员 Richardson 提出了
Richardson
成熟度模型,目的是为了找出 REST 架构风格和其他 Web 服务之间的关系。模型主要分为四个等级,级别越高,则越接近 REST 架构风格:
- Level-0 -> POX 沼泽(The Swamp of POX)
POX
=> Plain Old XML该级别下的 Web API 通常仅用作某个服务的
RPC
访问端点来使用,客户端通常会以 XML 等格式作为消息载体,与指定端点通信,例如:
POST => http://xxx.com/postsService
- 基于 XML 构建消息体,消息体内指定相应的远程调用的方法名及传入参数,这种形式被称为 RPC over HTTP
<postsService>
<GetDetails>
<PostId>20</PostId>
</GetDetails>
</postsService> - Level-1 -> 资源(Resource)
- 引入“资源”概念,围绕相应资源(用户、文章、产品等)进行相关操作,例如:
POST => http://xxx.com/getUserPosts // 关注用户文章数资源
POST => http://xxx.com/getUserStars // 关注用户收藏资源
POST => http://xxx.com/revokePost // 关注操作文章资源 - Level-2 -> HTTP 动词(HTTP Verbs)
- 使用特定的 HTTP 动词来表现其行为,具体请参考文章开头
API 的 URL 中使用特定名词
。
- 使用特定的 HTTP 动词来表现其行为,具体请参考文章开头
- Level-3 -> 超媒体控制(HyperMedia Controls)
- 最高级别 API,需要实现对超媒体应用状态引擎对应的约束,API 需要在响应消息中携带在当前状态下可以访问的其他相关资源的有效超链接,具体描述参考上文中的
4.统一接口
一栏。
- 最高级别 API,需要实现对超媒体应用状态引擎对应的约束,API 需要在响应消息中携带在当前状态下可以访问的其他相关资源的有效超链接,具体描述参考上文中的
如果我们的 Web API 在设计时只满足了上述四个等级中的一个,实际上并不能称为真正的
RESTful API
,有且至少要满足Richardson成熟度模型
中Level 3
的要求才能够达标,可以结合参考下 REST 架构作者Roy T. Fielding
博文中所言,If the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API.
,也许你能够得到一定的答案。- Level-0 -> POX 沼泽(The Swamp of POX)
总结
- 综上所述,我们可以发现,整个
REST架构风格
中,实际跟RESTful API
的设计目标没有实际太大关系,Richardson成熟度模型
存在的作用也只是对RESTful API
一个原始形态的描绘,但随着时间的发展,RESTful
一词逐渐演化成了一种API设计风格,REST 本质也逐渐被众人遗忘。