REST API是否真正符合REST原则?

3
我对这个游戏很陌生,可能会有误解。如果有人告诉我我误解了事情,那将是一种帮助。也许这个人会考虑足够多,向我展示正确的道路。但...
REST(http://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services)作为Web服务的一个“指南”或“最佳实践”之一是,在进行调用时应该使用适当的HTTP方法(我是否误解了它?)来调用REST API。
但是,查看网络上的许多API实现,我发现所有调用都是实际的GET调用,具体取决于它们的URI,将被API解释为其中一个HTTP动词或方法。
因此,例如,查看Twitter的REST API文档(https://dev.twitter.com/rest/public),原则上只定义了两个动词/方法(GET和POST),实际上所有调用都作为GET发送,并且根据GET调用中的URI进行解释并采取行动。
例如:
GET statuses / lookup:https://api.twitter.com/1.1/statuses/lookup.json POST statuses / update(PUT?):https://api.twitter.com/1.1/statuses/update.json 在这两种情况下,调用本身都是使用GET进行的,并且URI的最后一部分将其定义为真正的GET或POST。
总之,为了真正符合RESTful,Web服务的REST API的客户端实现不应该使用正确的HTTP动词/方法吗?
我错过了什么?

在这两种情况下,调用本身都是使用GET方法进行的。这具体是什么意思呢?您是否是指API接受常规的GET请求,即使文档中指定了POST?谁在“进行这些调用”?我不明白您想要表达什么。 - deceze
这可能会有所帮助;超媒体支持至关重要:https://docs.google.com/presentation/d/16bqtQz_sa_YgO6wlC8p-YK-ZTMWmrvyZiub7FupTT5M/edit#slide=id.p - Filip
1
模式和反模式:https://docs.google.com/presentation/d/1zhfqu7Wuy67J5fgz2jGh2I-kUpQblZpoWj3IQfp4yts/edit#slide=id.p - Filip
@filip26 很棒的资源。从名称上看,我猜你是作者。恭喜恭喜。 - acdcjunior
http://nishantshukla001webservices.blogspot.in/2015/09/webservices-soap-vs-rest-json-vs-xml.html - Nico
5个回答

12

你会错过很多内容,但不用担心,大部分人都会错过。

事实上,互联网上所谓的REST API中很少有真正符合RESTful标准的,主要是因为它们没有遵循超文本驱动的原则。REST成为了指代除SOAP以外的任何HTTP API的时髦术语,所以不要期望一个API真正符合RESTful标准只因其声称自己是REST API。我建议阅读这个答案。

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

REST由一系列约束条件定义。其中之一是统一接口,简单来说就是你不该改变底层协议的预期行为。REST没有与任何特定协议耦合,但由于它通常与HTTP一起使用,有时会变得复杂。

HTTP针对GET、POST、PUT、DELETE、PATCH和HEAD方法有非常明确的语义,而POST方法的语义由服务器确定。理想情况下,REST API应该对除POST以外的方法做出与RFC 7231规定完全相符的响应,但正如你所注意到的那样,有很多自称为RESTful的API并不能做到这点。造成这种情况的原因有很多。有时候只是对正确语义的简单误解,或者为了保持一致性,或者为了向不支持所有方法的中间件提供向后兼容性等等。

因此,要真正符合RESTful标准,需要做更多的工作,而仅仅正确使用HTTP方法是远远不够的。如果一个API甚至连这个都做不好,它就需要找另一个时髦词汇,因为它绝对不是REST。


非常棒的阅读。超文本部分绝对是重要的(Roy 本人说过,再直接不过了),但它经常被忽略(看看有多少 REST API 真正使用 HATEOAS!)。RFC 7231 的引用也非常有启发性。 - acdcjunior

2
你说得对。如果他们想要“符合REST原则”,他们的API应该尊重每个HTTP方法的语义。
大致上,REST关注于方法信息(服务器应该做什么)、作用域信息(服务器应该在哪里做)以及超媒体驱动(确保你查看@PedroWerneck在这个问题上的出色回答,它更详细地讨论了这个问题并引用了Fielding的一篇博客文章)。
你提到的API在URL中同时包含方法和作用域信息。这不太符合RESTful架构的特点,因为它在一般情况下告诉我们:
1)正确使用HTTP方法(尊重它们的属性,如幂等性等);
2)使用唯一的URI来标识唯一的资源。
第一点是“使用HTTP方法传达方法信息”,第二点是“使用URI传达作用域信息”。
再次说明,如果一个API使用GET方法并在URI中带有特定的参数来执行某些操作(而不是获取某些东西),那么它正在使用URI来传递方法信息。
现在,不要惊慌。大多数API都是RESTful-ish的(如Twitter或Flickr),这意味着它们是介于REST和其他东西之间的动物。这本身并不是坏事,只是意味着它们不能充分受益于RESTful架构(和HTTP)所提供的内容。
请记住,成为RESTful不仅仅是时尚问题,它确实有其好处,例如状态无关性、可寻址性等等。而这些好处只能通过正确使用HTTP动词来完全实现。
关于使用POST而非PUT,考虑到它们具有不同的属性(PUT是幂等的,POST则不是),只要设计统一,即程序员不必为API中每个URI所执行的POST操作而疑惑,那么使用POST并不算是“坏事”(PUT已经是统一的)。我在另一个问题(请查看“总结”部分)中详细讲解了这个问题,并引用了Roy Fielding的观点。

非常好的回答,但我在一个小点上不同意。POST方法在API中不必统一设计。POST方法的语义由目标资源确定,因此每个URI的行为有所不同是完全可以的,只要针对该媒体类型进行适当的文档记录即可。 - Pedro Werneck
@PedroWerneck 是的,我认为如果你对POST的统一定义是每个资源都有不同的含义,那么这是可以的。我从Roy在他的博客上的文章“使用POST是可以的”中得出了这个定义(统一性),你有机会看过吗?也许我们可以达成一致(我对此很感兴趣,如果我需要纠正自己也没有问题,因为我们在这里是为了学习,对吧? :) - acdcjunior
是的,那正是我得到定义的地方,也许我们只是用不同的词说同一件事。我对POST的统一定义是,它提交所包含的有效负载以供目标资源处理,与PUT相反,PUT要求服务器完全替换目标资源。目标资源对POST的有效负载做什么由媒体类型记录。正如Roy在那篇文章中所说,POST是适用于任何不值得标准化的操作的方法。 - Pedro Werneck

2
我无法确切地理解你的问题,但我相信有一些概念可以帮助你。让我详细说明一下...
你说得对,许多API在其API中使用了有限数量的HTTP“动词”。GET/POST是最常见的。PUT不太常见,其他所有方法(DELETE、HEAD、OPTIONS等)的使用概率越来越小。
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)

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:删除资源
您还需要了解它们可以应用于不同的级别,因此方法不会做相同的事情:
- 列表资源(例如,路径/elements) - 元素资源(例如,路径/elements/{elementid}) - 元素资源的字段(例如,路径elements/{elementid}/fieldname)。这对于使用多重基数管理字段值非常方便。您无需发送字段的完整值(整个列表),而是从中添加/删除元素。
另一个重要的事情是利用HTTP标头。例如,内容协商的标头Accept...
我认为Github的Web API设计得很好,其文档也很棒。您可以浏览它以获取想法。请参阅此处的文档:https://developer.github.com/v3/
希望这可以帮助您, Thierry

0

考虑查看REST Richardson Maturity Model主题。

这个规范是关于特定API的RESTful程度:

Level 0: 简单的GET和POST请求到描述性URL

/getUserByName?name=Greg

Level 1: 将所有内容分成资源并在资源组中定义操作

/user/getByName?name=Greg

Level 2: 正确使用HTTP动词。

GET /user/Greg

Level 3: 使用超媒体控件

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接