首页 文章

那个REST API真的是RPC吗?罗伊菲尔丁似乎在想

提问于
浏览
92

我认为我对REST的大量了解显然是错误的 - 而且我并不孤单 . 这个问题有很长的引导时间,但似乎是必要的,因为信息有点分散 . 如果你已经熟悉这个话题,最后会出现实际问题 .

从Roy Fielding的第一段REST APIs must be hypertext-driven开始,很明显他相信他的作品被广泛误解:

我对使用REST API调用任何基于HTTP的接口的人数感到沮丧 . 今天的例子是SocialSite REST API . 那就是RPC . 它尖叫RPC . 显示器上有很多耦合,应给予X等级 .

Fielding继续列出REST API的几个属性 . 他们中的一些人似乎反对SO和其他论坛的常见做法和共同建议 . 例如:

  • 应输入REST API,除了初始URI(书签)和适用于目标受众的标准化媒体类型集之外没有任何先验知识(即,任何可能使用API的客户端都应该理解) . ...

  • REST API不能定义固定资源名称或层次结构(客户端和服务器的明显耦合) . ...

  • REST API应该花费几乎所有的描述性工作来定义用于表示资源和驱动应用程序状态的媒体类型,或者为现有标准媒体类型定义扩展关系名称和/或启用超文本的标记 . ...

“超文本”的概念起着核心作用 - 远比URI结构或HTTP动词的含义更重要 . 其中一条评论中定义了“超文本”:

当我[菲尔丁]说超文本时,我指的是同时呈现信息和控制,使得信息成为用户(或自动机)获得选择和选择动作的可供性 . 超媒体只是对文本意味着在媒体流中包含时间锚点的扩展;大多数研究人员都放弃了这一区超文本不需要是浏览器上的HTML . 机器在理解数据格式和关系类型时可以跟踪链接 .

我猜这一点,但上面的前两点似乎表明,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可能会遵循上面的模式,但这不是重点 . )响应使用的媒体类型能够传达如何访问每个项目以及可以用它做什么,从而产生上述第三点 . 因此,API文档应侧重于解释如何解释响应中包含的超文本 .

此外,每次请求到Foo资源的URI时,响应都包含代理发现如何继续所需的所有信息,例如,通过其URI访问关联资源和父资源,或者在创建后采取措施/删除资源 .

整个系统的关键在于响应由媒体类型中包含的超文本组成,该超文本本身传达给代理选项以进行处理 . 它与浏览器为人类工作的方式没有什么不同 .

但这只是我在这个特殊时刻的最佳猜测 .

菲尔丁发表了一篇文章,其中他批评他的讨论过于抽象,缺乏例子和行话丰富:

其他人会试图以更直接或适用于当今实际问题的方式破译我所写的内容 . 我可能不会,因为我太忙于处理下一个话题,准备 Session ,写另一个标准,到一些遥远的地方旅行,或者只是做一些让我觉得自己赚到了薪水的小事 .

那么,REST专家的两个简单问题就是有一个实际的思维方式:你如何解释菲尔丁在说什么,以及在记录/实现REST API时如何将其付诸实践?

编辑:这个问题是一个例子,说明如果你不去讨论,学习一些东西有多难 . 在这种情况下,名称是"Hypermedia as the Engine of Application State"(HATEOAS) .

9 回答

  • 19

    我认为你的解释主要涵盖它 . URI是不透明的标识符,在大多数情况下,不应该进行通信超出用户代理用于访问应用程序的书签URI .

    至于记录,这个问题已经完成了很多次 . 您可以记录媒体类型及其包含的超链接控件(链接和表单),以及您希望的交互模型(请参阅AtomPub) .

    如果您记录URI或如何构建它们,那么您做错了 .

  • 4

    你的解释对我来说似乎是对的 . 我确实相信Fielding的约束可以实际应用 .

    我真的希望看到有人发布一些如何记录REST接口的好例子 . 有这么多糟糕的例子,有一些有效的例子指向用户将是非常有 Value 的 .

  • 4

    我一直在寻找一个在HATEOAS之后编写的API的一个很好的例子,但是找不到它(我发现SunCloud API和AtomPub的东西很难应用于“正常”的API情况) . 所以我尝试在我的博客上做一个真实的例子,跟随Roy Fieldings关于成为一个合适的REST实现意味着什么的建议 . 我发现很难提出这个例子,尽管它原则上相当简单(只是在使用API而不是网页时会感到困惑) . 我得到了Roy提出的问题并同意,这只是为了正确实现API的思维方式的转变 .

    看看:API Example using Rest

  • 1

    给出如何构建URI的指令的一个例外是允许在超文本响应中发送URI模板,其中字段由客户端自动替换,使用超文本中的其他字段 . 这通常不会节省很多带宽,因为gzip压缩会很好地处理URI的重复部分而不会打扰它 .

    关于REST和相关HATEOAS的一些很好的讨论:

    Advantages Of (Also) Using HATEOAS In RESTFul APIs

    How to GET a cup of coffee

  • 8

    对于那些感兴趣的人,我在Sun Cloud API中找到了HATEOAS的详细实例 .

  • 1

    大多数人出错的事情是(至少我认为)在REST世界中你没有记录你的“Rest界面”,你记录的是媒体类型,与你的服务器或服务无关 .

  • 5

    完全正确 . 我还要注意,只要模式来自服务器接收的文档(OpenSearch是一个合适的例子),URI模板在RESTful应用程序中就完全没问题了 . 对于URI模板,您可以记录它们的使用位置以及模板中预期的占位符,而不是模板本身 . 与Wahnfrieden所说的略有不同,这不是一个例外 .

    例如,在我的工作中,我们有一个内部域管理系统,服务文档指定了两个URI模板:一个用于为域资源生成最佳猜测URI,另一个用于构建用于查询域可用性的URI . 仍然可以翻阅域集合以找出给定域的URI是什么,但是考虑到它管理的域数量很大,这对于客户端来说是不可行的,所以给他们一个猜测是什么的方法从客户端的角度来看,域资源的URI可能是一个巨大的胜利,从服务器的带宽来看也是如此 .

    关于你的问题:我们的规范性文档是公开的资源,各种方法对这些资源的影响,使用的表示媒体类型及其模式,以及这些表示中的URI所指向的资源类型 .

    我们还包括非规范性(信息性)文档,其中附有免责声明,不会过多地阅读文档中提到的URI,该文档提供了典型客户端 - 服务器交互的示例 . 这使得相当抽象的规范性文件具体化 .

  • 4

    我想现在REST已经存在了很多年,技术专家已经接受了资源的概念以及真正的或不是RESTful的概念 .

    根据Richardson成熟度模型,有4个级别(0-3)定义了您的API的RESTful,其中3个意味着真正的RESTful API,正如Roy Fielding所预期的那样 .

    级别0是指您有一个入口点URI(如SOAP) .

    级别1意味着API能够区分不同的资源,并且具有多个入口点 - 仍然有SOAP的气味 .

    级别2是您使用HTTP谓词 - 主要是GET,POST,DELETE . 这是REST真正体现出来的水平 .

    在3级,你开始使用超媒体控件,使您的API真正RESTful .

    建议的进一步阅读链接:

  • 0

    假设 GET /foos/createForm 被调用以获取表单字段值,当我们去创建 POST /foos 时必须提供这些值 . 现在这个特殊的URL,即用于创建foos的1,应该根据Fielding的命题在 GET /foos/createForm 的响应中作为提交动作链接提及,对吧?
    那么映射动作到众所周知的Http动词到动作的好处是什么,"convention over code/config"是无效的 .

相关问题