3

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

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

但是看看网络上的许多 API 实现,我看到的是100% 对它们的调用实际上是GET调用,根据它们的URI,API 将被解释为 HTTP 动词或方法之一.

因此,例如,查看 Twitter 的 REST API 文档(https://dev.twitter.com/rest/public),它原则上只定义了两个动词/方法(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 动词/方法吗?

我错过了什么?

4

5 回答 5

11

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

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

根据我的经验,大多数 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。

于 2015-03-20T04:28:51.220 回答
2

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

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

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

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

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

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

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

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

希望它可以帮助你,蒂埃里

于 2015-03-20T09:36:23.907 回答
2

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

粗略地说,REST 是关于方法信息(服务器应该做什么)、范围信息(服务器应该在哪里做)以及,我几乎忘了提到,超媒体驱动(确保你检查@PedroWerneck 对这个问题的很好的回答,因为它说话关于它的更多信息,并参考了菲尔丁关于此事的博客文章)。

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

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

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

同样,如果 API 在 URI 中使用带有特定参数的 GET 来做某事(而不是获取某事),那么它就是在使用 URI 来传达方法信息。

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

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


关于使用POST而不是PUT,考虑到它们具有不同的属性(PUT是幂等的,POST不是),使用它也不错POST,只要它是统一设计的,也就是说,程序员应该不会想POST对每个URI做什么API:它们的行为都应该相同。(PUT不会因此受到影响,因为它已经是统一的了。)我对此进行了更多讨论 - 并引用了 Roy Fielding 的说法 - 在另一个问题中(查看“总结”部分)

于 2015-03-19T18:08:49.270 回答
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 概念是在Roy Fielding 的博士论文中“发明”的。如果你对这些事情感兴趣,那是一本很棒的书。

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

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

于 2015-03-19T18:17:56.660 回答
0

考虑查看REST Richardson 成熟度模型主题。

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

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

/getUserByName?name=格雷格

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

/user/getByName?name=格雷格

第 2 级: 正确使用 HTTP 动词。

获取/用户/格雷格

第 3 级: 使用超媒体控件

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

于 2015-10-26T14:46:00.667 回答