【问题标题】:Are REST API's really RESTful?REST API 真的是 RESTful 吗?
【发布时间】:2015-10-26 22:46:00
【问题描述】:

我是这个游戏的新手,所以我可能会误解一些事情。实际上,如果有人告诉我我对事情有误解,那将是一个人情。也许这个人会足够体贴,给我指明正确的道路。但是……

适用于 Web 服务 (http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services) 的 REST 的“指南”或“最佳实践”之一是您应该使用正确的 HTTP 方法 调用 REST API 时(我误解了吗?)。

但是查看网络上的许多 API 实现,我发现对它们进行的 100% 调用实际上是 GET 调用,具体取决于它们的 URI,将被 API 解释为 HTTP 动词或方法之一。

因此,例如,查看 Twitter (https://dev.twitter.com/rest/public) 的 REST API 文档,该文档原则上只定义了两个动词/方法(GET 和 POST),实际上所有调用都作为 GET 发送,并且基于GET 调用中的 URI,由 API 解释并执行。

例子:

获取状态/查找https://api.twitter.com/1.1/statuses/lookup.json

POST 状态/更新PUT?):https://api.twitter.com/1.1/statuses/update.json

在这两种情况下,调用本身都是使用 GET 进行的,并且 URI 的最后一部分将其定义为真正的 GET 或 POST。

总之,要真正实现 RESTful,Web 服务的 REST API 的客户端实现不应该使用正确的 HTTP 动词/方法吗?

我错过了什么?

【问题讨论】:

标签: api rest http-method httpverbs


【解决方案1】:

你错过了很多,但不要担心,大多数人都是。

事实上,互联网上很少有所谓的 REST API 是真正 RESTful 的,主要是因为它们不是 hypertext driven。 REST 成为了一个流行词来指代任何不是 SOAP 的 HTTP API,所以不要仅仅因为它说它是一个 REST API 就期望一个 API 真的是 RESTful。我建议阅读this 答案。

根据我的经验,大多数 API 开发人员并不了解 REST 的真正含义,并认为任何使用 HTTP 并避免在 URI 中使用动词的 HTTP API 都是 REST。

REST 由一组约束定义。其中包括统一接口,简单来说就是你不应该改变底层协议的预期行为。 REST 不与任何特定协议耦合,但由于与 HTTP 一起使用很常见,它们有时会变得复杂。

HTTP 为 GET、POST、PUT、DELETE、PATCH 和 HEAD 方法定义了非常明确的语义,而 POST 方法的语义由服务器决定。理想情况下,REST API 应该完全按照 RFC 7231 中的规定响应除 POST 之外的方法,但正如您所注意到的,有许多 API 称自己为 REST,但不这样做。发生这种情况有很多原因。有时对正确的语义存在简单的误解,或者是为了保持一致性,或者因为与不支持所有方法的中介的向后兼容性,以及许多其他原因。

因此,除了正确使用 HTTP 方法之外,还有很多工作要做才能真正实现 RESTful。如果一个 API 甚至没有做到这一点,它就需要找到另一个流行词,因为它绝对不是 REST。

【讨论】:

  • 很棒的阅读。超文本部分绝对很重要(好吧,Roy 自己说过,没有比这更直接的了),而且它经常被遗漏(哎呀,你有多少 REST API 看起来真的使用 HATEOAS?!)。对 RFC 7231 也有很好的参考。很有启发性。
【解决方案2】:

我无法准确说出您的问题是什么,但我相信有些概念会对您有所帮助。请允许我详细说明...

您说得对,许多 API 在其 API 中使用有限数量的 HTTP“动词”。 GET/POST 是最常见的。少放,然后所有其他(删除,头,选项等)都以消失的概率使用。

Dropbox Core API 用于文件上传允许可选的 PUT / POST 并且其声明的原因是“为了与浏览器环境兼容,也可以识别 POST HTTP 方法。”

确实限制是浏览器。流行的 Web 服务器对所有 HTTP 请求方法都没有问题,甚至是虚构的。毕竟,请求方法只是关于 Web 服务器的一些字符串。

HTML4 和 HTML5 只允许表单请求的 GET 和 POST 请求。如果您希望您的 API 完全可以通过浏览器使用 - 为什么不呢,这听起来很有用 - 那么您将仅限于 GET/POST。有关此问题的有用讨论,请参阅:https://softwareengineering.stackexchange.com/questions/114156/why-are-there-are-no-put-and-delete-methods-on-html-forms

更复杂的事情是 REST 不是行业标准。没有 RFC、ISO 或其他文档详细说明“合规”实现必须和不能做什么。虽然很多人一直在玩与 REST 相关的概念,但 REST 概念是在 PhD disseration of Roy Fielding 中“发明”的。如果你对这些事情感兴趣,那是一本很棒的书。

是的,根据 REST,API 应该使用正确的动词。但是,只要文档清楚,所有 GET 请求都是幂等的,那么生活应该会顺利进行。

(来源:我编写了 PipeThru.com,它集成了 40 多个 API,包括 Dropbox 和 Twitter)

【讨论】:

    【解决方案3】:

    我认为这个链接可以给你一些关于 RESTful 服务/Web API 设计的提示:https://templth.wordpress.com/2014/12/15/designing-a-web-api/

    很明显,并非所有声称是 RESTful 的 Web 服务都是真正的 RESTful ;-)

    简而言之,RESTful 服务应该利用 HTTP 方法来实现它们的设计目的:

    • 方法GET:返回资源状态
    • 方法POST:执行一个动作(在资源列表中创建一个元素,...)
    • 方法PUT:更新资源的完整状态
    • 方法PATCH:部分更新资源状态
    • 方法DELETE:删除资源

    您还需要注意它们可以应用于不同的级别,因此方法不会做同样的事情:

    • 列表资源(例如,路径/elements
    • 元素资源(例如,路径/elements/{elementid}
    • 元素资源的字段(例如,路径elements/{elementid}/fieldname)。这便于管理具有多个基数的字段值。您不必发送字段的完整值(整个列表),但可以从中添加/删除元素。

    另一个重要的事情是利用 HTTP 标头。比如内容协商的headerAccept...

    我发现 Github 的 Web API 设计得很好,它的文档也很棒。您可以浏览它以产生想法。在此处查看其文档:https://developer.github.com/v3/

    希望对你有帮助 蒂埃里

    【讨论】:

      【解决方案4】:

      你是对的。如果他们想要“RESTful”,他们的 API 应该尊重每个 HTTP 方法的语义。

      大致上,REST 是关于方法信息服务器应该做什么)、范围信息位置服务器应该这样做),而且我差点忘了提到,超媒体驱动(请务必查看@PedroWerneck's great answer to this question,因为它会更多地谈论它,并参考菲尔丁关于此事的博客文章)。

      您提到的 API 的作用是在 URL 中同时包含方法和范围信息。这不太适合 RESTful 架构,因为一般来说,它告诉我们:

      • 1) 以正确的方式使用 HTTP 方法(尊重它们的属性,例如幂等性等),并且
      • 2) 使用唯一 URI 来标识唯一资源。

      第 1 点说“使用 HTTP 方法传递方法信息”,第 2 点说“使用 URI 传递范围信息”。

      同样,如果 API 使用 GET 和 URI 中的特定参数来 do 某事(而不是 get 某事),那么它就是使用 URI 来传达方法信息.

      现在,不要惊慌。大多数 API 都只是 RESTful-ish(如 flickr 的 twitter),这意味着它们是介于 REST 和其他东西之间的动物。这本身还不错,只是意味着他们不会充分受益于 RESTful 架构(和 HTTP)所提供的功能。

      请记住,RESTful 不仅仅是一种时尚问题,它确实有它的好处,例如无状态性、可寻址性等等。而这些只能通过使用应该使用的 HTTP 动词来完全实现。


      关于使用POST 代替PUT,考虑到它们具有不同的属性(PUT 是幂等的,POST 不是),使用POST 并不是不好,只要它是统一设计的,也就是说,程序员不应该想知道POST 将为 API 中的每个 URI 做什么:它们都应该表现相同。 (PUT 不会因此受到影响,因为它已经是统一的了。)我在another question (check out the "Wrapping Up" part) 中对此进行了更多讨论 - 并引用了 Roy Fielding 的说法。

      【讨论】:

      • 很好的答案,但我有一点不同意。 POST 不必跨 API 统一设计。 POST 方法的语义由目标资源确定,因此每个 URI 具有不同的行为是完全可以的,只要它为该媒体类型正确记录即可。
      • @PedroWerneck 是的,我想如果你对POST 的统一定义是每个资源对它都有不同的含义,我想没关系。我从 Roy 在他的博客"It's okay to use POST" 上的帖子中得到了这个定义(统一性),你有机会检查一下吗?也许我们可以达成一致意见(我对此很感兴趣,如果我必须纠正自己也没问题,因为我们是来学习的,对吧?:)。
      • 是的,这正是我得到我的定义的地方,所以也许我们只是用不同的词说同样的事情。我对 POST 的统一定义是它提交封闭的有效负载以由目标资源处理,这与 PUT 相反,例如,它要求服务器完全替换目标资源。目标资源对 POSTed 有效负载的作用由媒体类型记录。正如 Roy 在那篇文章中所说,POST 是执行任何不值得标准化的操作的方法。
      【解决方案5】:

      考虑查看REST Richardson Maturity Model 主题。

      本规范是关于 RESTful 特定 API 的数量:

      0 级: 对描述性 url 的简单 GET 和 POST 请求

      /getUserByName?name=Greg

      1 级: 划分资源中的所有内容并在资源组中定义动作

      /user/getByName?name=Greg

      2 级: 正确使用 HTTP 动词。

      GET /user/Greg

      3 级: 使用超媒体控件

      不同的 API 实现不同的 REST 成熟度级别。这就是为什么某些 API 不支持所有 HTTP 功能的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-25
        • 2018-02-10
        • 1970-01-01
        • 2018-09-29
        • 2011-05-04
        • 2016-09-06
        • 2014-10-17
        • 2011-08-15
        相关资源
        最近更新 更多