那REST API真的是RPC吗? 罗伊·菲尔丁似乎认为如此
我认为我所知道的REST的大部分显然是错误的 – 我并不孤单。 这个问题有很长的导入,但似乎是必要的,因为信息有点分散。 如果你已经熟悉这个话题,最后的问题就来了。
从Roy Fielding的REST API的第一段必须是超文本驱动的 ,很清楚他相信他的工作正在被广泛的误解:
我感到沮丧的人调用任何基于HTTP的接口REST API的人数。 今天的例子是SocialSite REST API 。 这是RPC。 它尖叫着RPC。 显示器上有这么多的耦合,应该给它一个X等级。
Fielding继续列出REST API的几个属性。 他们中的一些人似乎不赞成SO和其他论坛的惯例和共同意见。 例如:
-
除了最初的URI(书签)和适合于目标受众的标准化媒体types(即预期被任何可能使用API的客户端所理解)的集合之外,REST API应该在没有任何先前知识的情况下被input。 …
-
REST API不能定义固定的资源名称或层次结构(客户端和服务器明显的耦合)。 …
-
REST API应该花费几乎所有的描述性努力来定义用于表示资源和驱动应用程序状态的媒体types,或者为现有标准媒体types定义扩展关系名称和/或启用超文本的标记。 …
“超文本”的概念起着核心的作用 – 比URI结构或HTTP动词更重要。 “超文本”是在其中一个评论中定义的:
当我(Fielding)说超文本时,我的意思是同时呈现信息和控制,使得信息成为用户(或自动机)通过其获得select和select动作的可供件。 超媒体只是文本意味着在媒体stream中包含时间锚的扩展; 大多数研究者已经放弃了这一区分
超文本在浏览器上不需要是HTML。 机器在理解数据格式和关系types时可以遵循链接。
我猜在这一点上,但上面的前两点似乎表明,类似于以下的Foo资源的API文档导致客户端和服务器之间的紧密耦合,并且在RESTful系统中没有地位。
GET /foos/{id} # read a Foo POST /foos/{id} # create a Foo PUT /foos/{id} # update a Foo
相反,代理应该被迫发现所有Foos的URI,例如,发出一个针对/ foos的GET请求。 (这些URI可能会遵循上面的模式,但那不是重点。)响应使用媒体types,能够传达如何访问每个项目以及可以使用哪些项目,从而产生了上述第三点。 因此,API文档应重点解释如何解释响应中包含的超文本。
此外,每次请求URI到Foo资源时,响应都包含代理发现如何继续执行所需的所有信息,例如,通过URI访问关联资源和父资源,或者在创build之后采取行动/删除资源。
整个系统的关键在于响应由包含在媒体types中的超文本组成,该媒体types本身传达给代理选项以进行处理。 这与浏览器为人类工作的方式不同。
但是这只是我在这个特殊时刻的最佳猜测。
菲尔丁发表了一个后续行动 ,他回应了批评他的讨论太抽象,缺乏实例和行话丰富:
其他人会试图用我们今天所关心的更直接或者更适用的方式来破译我所写的内容。 我可能不会,因为我忙于应付下一个话题,准备召开一个会议,写另一个标准,到一个遥远的地方旅行,或者做一些让我觉得我已经获得了薪水的小事情。
因此,对于REST专家来说,有两个简单的问题需要一个实际的思路:您如何解释Fielding的说法,以及在logging/实现REST API时如何将其付诸实践?
编辑:这个问题是一个例子,如果你没有一个你正在谈论的名字的话,学习这个东西有多难。 在这种情况下的名称是“超媒体作为应用程序状态引擎”(HATEOAS)。
我认为你的解释大多覆盖了它。 URI是不透明的标识符,大多数情况下,这些标识符不应该在用户代理用来访问应用程序的书签URI之外进行传送。
至于文件logging,这个问题已经做了不less次了。 如果您愿意(请参阅AtomPub),则logging您的媒体types及其包含的超链接控件(链接和表单)以及交互模型。
如果你loggingURI或者如何构build它们,那么你就错了。
你的解释对我来说似乎是对的。 我相信菲尔丁的限制可以实际应用。
我真的希望看到有人发表一些如何loggingREST接口的好例子。 有这么多可怜的例子,有一些有效的指向用户将是非常有价值的。
指导如何构buildURI的一个例外是允许在超文本响应中发送URI模板,其中字段由客户自动replace,使用超文本中的其他字段。 这通常不会节省很多带宽,因为gzip压缩将足够好的处理URI的重复部分,以免打扰。
关于REST和相关的HATEOAS的一些很好的讨论:
(也)在RESTFul API中使用HATEOAS的优点
如何获得一杯咖啡
对于那些感兴趣的人,我在Sun Cloud API的实践中find了一个HATEOAS的详细例子。
我一直在寻找一个在HATEOAS之后编写的API的例子,并且很难find一个(我发现SunCloud API和AtomPub的东西很难适用于“正常”的API情况)。 所以我试着在我的博客上做一个现实的例子,遵循Roy Fieldings关于什么是合适的REST实现的意见。 我发现很难拿出这个例子,尽pipe它原则上相当简单(只是在使用API而不是网页时使用混淆)。 我得到了罗伊对这个问题的看法,并且同意,这只是一个恰当地实现API的转变。
看看: 使用Rest的API示例
大多数人错误的是(至less我认为)在REST的世界里,你不logging你的“Rest界面”,你logging的是媒体types,与服务器或服务无关。
完全正确。 我还要注意,只要模式是从服务器接收到的文档(OpenSearch是一个合适的例子),那么这个URI模板在RESTful应用程序中是完全正确的。 对于URI模板,您logging了它们的使用位置以及模板中的预期占位符,而不是模板本身。 与Wahnfrieden所说的略有相反,这不是一个例外。
例如,在我的工作中,我们有一个内部域pipe理系统,服务文档指定了两个URI模板:一个用于为域资源生成最佳猜测URI,另一个用于构build用于查询域可用性的URI。 仍然有可能通过域集合来查找给定域的URI是什么,但是由于它pipe理的域数量很大,这对于客户端来说是不可行的,所以给他们一个猜测从客户的angular度来看,域名资源的URI可能是一个巨大的胜利,而从服务器的带宽来看,这是一个巨大的胜利。
关于您的问题:我们的规范性文档是暴露的资源,各种方法对这些资源的影响,所使用的表示媒体types及其模式,以及这些表示中的URI所指向的资源types。
我们还包括非规范性的(资料性的)文档,它附带了一个免责声明,不要过多地读入文档中提到的URI,它提供了典型的客户端 – 服务器交互的例子。 这就把相当抽象的规范性文件具体化。
我想REST现在已经有多less年了,技术人员已经接触到一个资源的概念,什么是真正的或者不是RESTful。
根据Richardson成熟度模型,有4个级别(0-3)定义了RESTful API的含义,3代表真正的RESTful API,就像Roy Fielding所预期的那样。
级别0是当你有一个入口点的URI – 像SOAP。
级别1意味着API能够区分不同的资源,并且具有多个入口点 – 仍然具有SOAP的气味。
2级是当你使用HTTP动词 – 主要是GET,POST,DELETE。 这是REST真正进入图片的水平。
在第3级,您开始使用超媒体控件来使您的API 真正成为 RESTful。
build议的链接进一步阅读:
- 理查森成熟度模型是什么?
- 马丁福勒的博客:理查森成熟度模型
我们假设调用GET /foos/createForm
来获取表单字段值,当我们去创buildPOST /foos
时必须提供这些值。 现在这个特殊的URL,也就是用于创buildfoos的1应该在GET /foos/createForm
的响应中作为一个提交动作链接来提及,根据Fielding的主张,对吧?
那么映射动作到知名的Http动词到动作的好处是什么,“约定的代码/configuration”的东西是无效的。