RESTful API无处不在。这很有趣,因为有多少人真正知道“休息”应该是什么意思呢?
我读过几篇关于REST的文章,甚至是一些原文。但是对于它是什么,我仍然有一个相当模糊的概念。我开始认为没有人知道,这只是一个非常模糊的概念。
我曾计划写一篇博客文章,探索REST是如何成为互联网上交流的如此重要的范例的。我从阅读罗伊·菲尔丁(Roy Fiding)2000年的论文开始我的研究,这篇论文向世界介绍了REST。读完菲尔丁的论文后,我意识到这里更有趣的故事是菲尔丁的思想是如何被如此广泛地误解的。
更多的人知道菲尔丁的论文是REST的来源,而不是读过这篇论文(这是公平的),所以对论文实际内容的误解是普遍存在的。
这些误解中最大的误区是,本文直接针对API的构建问题。我一直认为,正如我想象的许多人所做的那样,REST从一开始就打算作为构建在HTTP之上的WebAPI的体系结构模型。我想也许曾经有过一段混乱的实验期,人们在HTTP上构建API都是错误的,然后Fiding出现了,并将REST作为明智的方式来做事情。但时间线在这里没有意义:从我们今天所知的意义上讲,Web服务的API直到Fielding发表他的论文几年后才成为一件事。
Fiding的论文(标题为“体系结构样式和基于网络的软件体系结构的设计”)不是关于如何在HTTP之上构建API,而是关于HTTP本身。Fiding对HTTP/1.0规范做出了贡献,并与人合著了HTTP/1.1规范,该规范于1999年发布。他对可以从HTTP协议设计中学到的体系结构课程很感兴趣;他的论文将REST描述为指导HTTP/1.1标准化过程的体系结构原则的补充。Fiding使用这些原则来决定将哪些建议合并到HTTP/1.1中。例如,他拒绝了使用新的MGET和MHEAD方法批处理请求的提议,因为他认为该提议违反了REST规定的约束,特别是REST系统中的消息应该易于代理和缓存的约束。1因此HTTP/1.1是围绕可以发送多个HTTP请求的持久连接而设计的。(Fiding还认为Cookie不是RESTful的,因为它们为本应是无状态的系统添加了状态,但它们的使用已经根深蒂固。2)对于Fiding来说,REST不是构建基于HTTP的系统的指南,而是扩展HTTP的指南。
这并不是说Fiding不认为REST可以用来构建其他系统。只是他假设这些其他系统也将是“分布式超媒体系统”。这是人们对REST的另一个误解:认为它是可以用于任何类型的网络应用程序的通用架构。但是你可以把论文中菲尔丁介绍REST的部分归结为:“听着,我们刚刚设计了HTTP,所以如果你也发现自己在设计一个分布式超媒体系统,那么你应该使用我们设计的这个叫做REST的很酷的体系结构来让事情变得更简单。”考虑到Web已经存在,为什么菲尔丁会认为有人会尝试构建这样的东西,这一点并不明显;也许在2000年,世界上似乎有不止一个分布式超媒体系统的空间。无论如何,Fiding明确表示,REST旨在解决试图通过互联网连接超媒体时出现的可伸缩性和一致性问题,而不是作为分布式应用程序的总体架构模型。
我们现在记得Fiding的论文是介绍REST的论文,但实际上这篇论文是关于一刀切的软件体系结构有多烂,以及如何更好地选择适合您需求的软件体系结构。这篇论文只有一章专门介绍REST本身;大部分字数都花在了可以用于网络应用程序的可选架构风格的分类上。其中包括受UnixPipes启发的管道和过滤器(PF)样式,以及客户端-服务器样式(CS)的各种改进,例如分层客户端服务器(LCS)、客户端缓存无状态服务器(C$SS)和分层客户端缓存无状态服务器(LC$SS)。缩写变得笨拙,但Fiding的观点是,您可以混合和匹配现有样式施加的约束,以派生新样式。REST是以这种方式派生出来的,也可能会被调用-但原因很明显:wasnot—Uniform-Layered-Code-on-Demand-Client-Cache-Stateless-Server(ULCODC$SS)。字段建立此分类是为了强调不同的AP适用不同的约束
这是今天REST无处不在的深刻讽刺。REST现在被盲目地用于各种网络应用程序,但Fiding最初提供REST是为了说明如何根据单个应用程序的特定需求派生软件体系结构。
我很难理解这是怎么发生的,因为菲尔丁非常清楚不让形式遵循功能的陷阱。他几乎在论文一开始就警告说,由于未能正确理解软件体系结构,“用流行语进行设计是司空见惯的事情”。4几页后,他又拿起这个主题:
有些架构风格经常被描绘成适用于所有软件形式的“银弹”解决方案。然而,一个好的设计师应该选择一种与正在解决的特定问题的需要相匹配的风格。5个。
REST本身是一个特别糟糕的“银弹”解决方案,因为正如Fiding后来指出的那样,它包含了一些可能不合适的权衡,除非您正在构建分布式超媒体应用程序:
REST设计用于大粒度超媒体数据传输,针对Web的常见情况进行了优化,但其界面对于其他形式的架构交互并不是最优的。6个。
菲尔丁之所以提出REST,是因为网络带来了一个棘手的“无政府可扩展性”问题,即菲尔丁的意思是需要以不符合规则的方式跨越组织和国家边界连接文档。REST施加的约束经过精心选择,以解决这种无政府状态的可伸缩性问题。面向公众的Web服务API必须处理类似的问题,因此可以理解为什么REST与此相关。然而,今天,如果发现一个工程团队已经使用REST构建了一个后端,即使该后端只与工程团队完全控制的客户对话,也不会令人惊讶。我们都成为了这幅Monty Python素描中的建筑师,他设计了一座屠宰场风格的公寓建筑,因为屠宰场是他唯一有经验的建筑。(菲尔丁用这张素描中的一句话作为他论文的题词:“对不起,…。你是说‘刀子’吗?“)。
那么,既然Fiding的论文都是关于避免银弹软件架构的,那么REST是如何成为各种web服务的事实标准的呢?
我的理论是,在本世纪头十年中期,那些厌倦了肥皂并想做其他事情的人需要他们自己的四个字母的缩写。
我在这里只是半开玩笑。SOAP,即简单对象访问协议,是一种简单而复杂的协议,如果不先了解一系列相互关联的XML规范,就不能使用它。早期的Web服务提供了基于SOAP的API,但随着2000年代中期越来越多的API开始提供,被SOAP的复杂性所困扰的软件开发人员纷纷离开。
在这群人中,肥皂招致了鄙视。Ruby-on-ail在2007年放弃了对SOAP的支持,这导致了铁路编剧David Heinemeier Hansson的象征性评论:“我们觉得SOAP过于复杂。它已经被企业员工接管了,当这种情况发生时,通常没有什么好结果。”7“企业员工”希望所有的事情都被正式指定,但那些想要完成的人群认为这是浪费时间。
如果垃圾人群不打算使用SOAP,他们仍然需要一些标准的做事方式。由于每个人都在使用HTTP,而且由于所有的代理和缓存支持,每个人至少都会继续使用HTTP作为传输层,所以最简单的做法就是依赖HTTP的现有语义。所以他们就是这么做的。他们可以将他们的方法命名为Fuck It,Overload HTTP(FIOH),这将是一个准确的名称,任何试图决定为业务逻辑错误返回什么HTTP状态代码的人都可以证明这一点。但是,与进入SOAP的所有正式规范工作相比,这似乎是不顾一切的枯燥乏味。
幸运的是,有一篇论文是由http/1.1规范的合著者撰写的,它隐约与扩展HTTP有关,可以给FIOH披上学术的外衣。所以休息是为了掩护真正只有FIOH的东西。
我并不是说事情就是这样发生的,也不是说不敬的初创公司类型之间存在着挪用REST的实际阴谋,但这个故事帮助我理解了当菲尔丁的论文根本不是关于Web服务API的时候,REST是如何成为Web服务API的模型的。采用REST的约束有一定的意义,特别是对于跨越组织边界并因此受益于REST的“统一接口”的面向公众的API。这个链接一定是为什么在Web上构建API时首次提到REST的核心原因。但是想象一下另一种称为“FIOH”的方法(部分出于市场原因借用了“REST”这个名称),可以帮助我解释今天我们所知的RESTfulAPI和Fiding最初描述的REST架构风格之间的许多差异。
例如,REST纯粹主义者经常抱怨所谓的RESTAPI实际上不是RESTAPI,因为它们不使用超媒体作为应用程序状态的引擎(HATEOAS)。根据他的说法,真正的rest API应该允许您通过以下链接从基端点导航其所有端点。如果您认为人们实际上是在尝试构建RESTAPI,那么这是一个明显的遗漏-HATEOAS确实是Fiding的REST原始概念的基础,特别是考虑到“表示状态转移”中的“状态转移”指的是使用资源之间的超链接来导航状态机(而不是像许多人似乎认为的那样,通过网络转移资源资产)。8但是,如果您想象每个人都只是构建FIOHAPI并将其作为REST API(或者更老实地说是“RESTful”API)进行广告,那么HATEOAS当然就不重要了。
同样,您可能会惊讶地发现,Fiding的论文中没有任何关于哪个HTTP谓词应该映射到哪个CRUD操作的内容,尽管软件开发人员喜欢无休止地争论使用PUT还是补丁更新资源更具REST风格。拥有HTTP动词到CRUD操作的标准映射是一件很有用的事情,但是这个标准映射是FIOH的一部分,而不是REST的一部分。
这就是为什么我们不应该说没有人理解休息,而应该认为“休息”这个词已经被盗用了。最新API的现代概念与Fiding的REST体系结构有历史上的联系,但实际上这两件事是分开的。作为何时构建RESTful API的指南,请牢记历史链接。您的API是否像HTTP需要的那样跨越组织和国家边界?那么,构建具有可预测的统一接口的RESTfulAPI可能是正确的方法。如果不是,记住Fiding更喜欢使用Form Follow函数。也许像GraphQL或者仅仅是JSON-RPC这样的东西会更适合您正在努力实现的目标。
如果你喜欢这个帖子,那就更像是每四周出一次!在Twitter上关注@TwoBitHistory或订阅RSS feed,确保你知道什么时候有新帖子发布。
新帖子发布了!我写了一篇关于如何使用30年代的模拟计算机解微分方程的文章,这些计算机大多是由齿轮制成的。作为一个额外的好处,这里甚至有一些关于如何瞄准非常大的火炮的东西。https://t.co/fwswXymgZa。
-TwoBitHistory(@TwoBitHistory)2020年4月6日。
罗伊·菲尔丁。“体系结构风格和基于网络的软件体系结构的设计”128。2000年。加州大学欧文分校,博士论文,2020年6月28日访问,https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation_2up.pdf./↩。
菲尔丁区分了软件架构和软件架构“风格”。REST是一种架构风格,在Http架构中有一个实例化。↩。
保罗·吉尔。“为Web应用发布的Ruby on rails 2.0”,InfoWorld。2007年12月7日,访问时间:2020年6月28日,https://www.infoworld.com/article/2648925/ruby-on-rails-2-0-released-for-web-apps.html:↩