| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
jopen
9年前发布

简单识别 RESTful 接口

本文描述了识别一个接口是否真的是 RESTful 接口的基本方法。符合 REST 架构风格的接口,称为 RESTful 接口。本文不打算从架构风格的推导方面描述,而是从 HTTP 标准的方面描述。识别的方法同时也是指导实践的原则。


一、是否使用了正确(合适)的方法


目前对于 HTTP 标准滥用较多的,就是方法。谈起 RESTful 接口的方法,很多资料告诉大家,说 GET、POST、PUT、DELETE,分别对应数据库操作的 SELECT、INSERT、UPDATE、DELETE。其实这种理解是不正确的。


方法有两个性质:安全性与幂等性;以及一个语义:动作本身的意思。RESTful 接口为各种数据抽象为资源,对资源的操作,主要是依据方法的两个性质,其次才是语义。


GET 方法的语义是获取资源,性质是安全、幂等。也就是说,对资源进行安全幂等的操作,应该用 GET 或 HEAD,当目的是获取资源时,选用 GET,目的是获取资源的元数据时,使用 HEAD。使用安全幂等的方法执行不安全或不幂等的操作,都是错误的。一个典型的例子是:


GET /book/357?op=delete


这个例子的意图是删除 ID 为 357 的 book,DELETE 是不安全的操作,却使用了 GET 这个安全幂等的操作。这作法的副作用是可能被缓存,所有组件(包括搜索引擎)都认为它是安全的,从而可能不加任何限制地对它进行访问。


POST 方法的语义是提交资源。“提交”本身就是一个比较抽象的动词,即它的语义是可以根据环境变化的,如果将它与 INSERT 对应起来,是以偏概全的。它的性质是不安全、不幂等。这意味着所有组件对它都不缓存,不重复发送请求。执行不安全、不幂等的操作,唯有选择 POST 方法(标准未规定的所有自定义方法,在性质上等同于 POST)。


一个不安全、不幂等的方法,可以执行安全、幂等的操作,前提是需要牺牲缓存等属性。比如提交一个很多参数的查询,可以使用 POST。


HTTP/1.1标准那么多年,HTML标准到5了,为什么HTML的 form 只有 GET 和 POST 两种 action ?为没有不把 PUT、DELETE、PATCH 等方法加进去?其实是有原因的。


首先,form 元素的提交表单的按钮是 submit,与 POST 的语义是等同的。


其次,当浏览器获得一个资源时,form 只是资源的一部分,不能表示整个资源,根据 PUT/DELETE/PATCH 的定义,它无法表示它们。


由于 POST 的性质与抽象的语义,在没有合适的方法时,都可以使用 POST 代替。因此,将 POST 等同于新增/插入的那些文章或教材,都在误导人。


篇幅有限,其它方法不说了,网上基于其它方法的文章基本正确的。


二、是否支使媒体协商


媒体协商是指客户端和服务器对某种媒体类型的处理能力。一般情况下,客户端并不知道服务器能处理哪种媒体。浏览器就是典型代表,它在无先验知识的情况下,会进行媒体探测:


GET / HTTP/1.1  Host: example.com  Accept: text/html; q=1.0, image/*; q=0.8, */*; q=0.1


这是告诉服务器,我能非常有效地处理 HTML 类型的资源,图片也是很有效的,其它的资源类型,我也能接受。于是服务器就优先按 HTML 返回资源,如果没有 HTML 或 Image,就返回服务器自身最合适的,如 application/json。


假设服务器仅支持 application/json,当客户端要求一个 application/xml 时,应当返回 415 Unsupported Media Type,并在正文中说明支持哪种媒体类型。


举个值得学习的案例,Github:https://api.github.com/ ,大家可以自己试试。


三、是否能够进行状态转移


这一点非常重要,也是 REST 的本意,状态转移!HTTP 标准实现的 REST 中,连接(Link)是实现状态转移的重要组件(HTML 的超链接和表单也是)。


在无先验知识的前提下,客户端请求资源 / ,这个资源及其元数据,要能够为应用程序的下一个状态的转移提供必要的连接。有时候甚至要提供文档说明的连接。


例如,当我们访问 https://api.github.com/ 时,我们看到一个连接的列表。通过这些连接,我们的客户端就可以跳转到另一个状态,从而实现整个应用程序的状态转移。状态如何更好的转移(甚至是自动化的状态转移),就要依赖于连接的关系(rel)以及连接的媒体类型(type)和可选的文档。


这种状态转移的能力,正是 REST 的魅力。诚然,最成功的 REST 客户端是浏览器,最成功的媒体类型是 text/html,最成功的 REST 是 HTTP,通过 URI 标准构建的连接,进化成我们今天无法量化的巨大的分布式系统:Web。


额外一点,一个 RESTful 的接口是不需在路径或头部字段中使用接口的版本号的。RESTful 接口这种说法,也有误。REST有统一接口的概念,但这个概念一般是指 HTTP 标准。在一个 RESTful 的环境中,一切事物都是资源,资源是没有版本号的。版本号是 API 的概念,API 是 RPC 的事物。


资源一旦发布,其结构就基本上不再发生变化。唯一能够变化的资源结构是在对旧资源无副作用的前提下,新增资源的字段或属性。当新增或删除的属性与当前资源的结构不兼容时,则需要增加一个或一类新的资源。因此,在 RESTful 实践中,是不需要使用版本号来标识资源的。


当然,RESTful 内容的丰富,远远不止以上所提到的三点。但这三点是非常基本的要求。


 本文由用户 jopen 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1432468281150.html
RESTful WEB服务/RPC/SOA