为什么使用HTTP PUT和DELETE方法而不是POST?

new_story GET /story/new(.:format) {:action=>"new", :controller=>"stories"} edit_story GET /story/edit(.:format) {:action=>"edit", :controller=>"stories"} story GET /story(.:format) {:action=>"show", :controller=>"stories"} PUT /story(.:format) {:action=>"update", :controller=>"stories"} DELETE /story(.:format) {:action=>"destroy", :controller=>"stories"} POST /story(.:format) {:action=>"create", :controller=>"stories"} 

在网络工作中,我已经完成了其他技术,我只使用过GET和POST方法。 但是在Rails中使用RESTful路由时,默认情况下,PUT和DELETE方法用于更新和销毁操作。 使用PUT和DELETE的优点或需求是什么? 我假设这些方法只是做POST的另一种方式 – 但为什么不坚持使用POST?

优点主要是语义,也可以在一定程度上简化URL。 不同的HTTP方法映射到不同的操作:

 POST => create a new object DELETE => delete an object PUT => modify an object GET => view an object 

然后,理论上,您可以使用相同的 URL,但使用不同的方法与它进行交互; 用于访问资源的方法定义了实际的操作类型。

但实际上,大多数浏览器只支持HTTP GET和POST。 Rails使用HTML表单中的一些“技巧”来表现就好像发送了PUT或DELETE请求一样,即使Rails仍在使用GET或POST这些方法。 (这解释了为什么您可能没有在其他平台上使用DELETE或PUT。)

这是HTTP 1.1规范的“方法”部分 ; 它定义了许多方法,它们都有不同的好处和权衡。 POST是最灵活的,但权衡很多:它不可缓存(因此互联网的其余部分无法帮助您扩展),它不安全或幂等,因此客户端不能只重新发送它会出错,并且不再清楚你要完成的是什么(因为它非常灵活)。 我确信还有其他人,但这应该足够了。 考虑到所有这些,如果HTTP规范定义了一个完全符合您的请求要求的方法,则没有理由发送POST

POST很常见的原因是,至少在历史上,Web浏览器只支持GETPOST 。 由于GET被定义为安全且幂等(即使许多应用程序不遵守),修改数据的唯一安全方法是发送POST 。 随着AJAX和非浏览器客户端的兴起,这已不再适用。

顺便说一下,@ mipadi给出的映射是标准映射,但它不是唯一有效的映射。 例如,Amazon S3使用PUT创建资源。 使用POST的唯一原因是客户端没有足够的知识来创建资源,例如,您使用关系数据库备份资源并使用人工代理键​​。

当你可以将其内容设置为零字节并且文件系统将其视为删除时,这有点像问为什么“删除”文件。 HTTP一直支持除GET / POST之外的动词,但SOAP进化的方式有点扭曲了这些动词的原始含义。 REST是一种更简单的回归基础方法,它使用动词,而不是在有效载荷内部发明一些新的动词概念。

我只想在接受的答案中添加一些内容,因为他对http verbs定义不正确。 它们都有一个“应该”遵循的规范,您可以根据规范创建/更新/删除多个http verbs

我将重点介绍W3的RFC 2616中的一些重要部分

我将从PUT开始,因为在我看来它围绕着它最混乱。

  • PUT is used for both create/update PUT updates by completely replacing the resource on the server with the resource sent in the request

例如

你打电话给我的api

 PUT /api/person { Name: John, email: jdoe@hra.com } 

我的服务器有这个资源存在于服务器上

 { Name: Jane, email: jdoe@hra.com } 

现在我的现有资源完全被您发送的内容所取代,这就是我在服务器上的内容。

 { Name: John, email: jdoe@hra.com } 

因此,如果您PUT并且只在身体中发送电子邮件

 PUT /api/person { email: jdoe@hra.com } 

我的服务器将完全取代实体

 { Name: Jane, email: jdoe@hra.com } 

 { email: jdoe@hra.com } 

名字将消失。 部分更新适用于PATCH但无论如何我都使用POST

  • One of the main reasons why we create/update with put is because it is idempotent.

它只是一个奇特的术语,它的基本定义是对于单个请求,多个相同的请求是相同的。

假设我将文件输出到api/file如果源服务器没有找到该文件,它将创建一个文件。 如果它找到了一个文件,它将完全用我发送的文件替换旧文件。 这可确保创建和更新一个文件。 如果没有文件存在并且您调用PUT 5次,则第一次创建文件时,另外4次将文件替换为您发送的文件。 如果您调用POST 5次来创建它将创建5个文件。

  • You PUT to that exact URI. If you don't you have to send a 301 (Moved Permanently) to the user and allow then make a choice whether or not to redirect the request. Most times the server you PUT to usually hosts the resource and takes care of updating it

这些是何时使用PUT的主要观点

POST而言

  • You can also create/update and then some...

正如我上面提到的,有一些关键的区别。

  • 邮政更通用。 以什么方式? 其他一些示例包括其他协议的网关,它可以接收响应并将其发送到某些数据处理程序中,或者它可以扩展某种function。
  • Post没有“To the exact URI or notifiy”的限制,例如POST可以将资源附加到现有集合并确定它的存储位置。

那么Delete为什么我不只是POST

当您DELETE ,服务器不应该 成功响应,除非您删除资源或在发送响应时将其移动到不可访问的位置。

为什么这很重要? 如果你调用DELETE但资源在被删除之前必须通过“APPROVAL”怎么办? 如果可以拒绝删除,则无法发送成功的错误代码,如果您遵循此基本规范,则会使调用者感到困惑。 举个例子,我相信你能想到很多其他人。

我刚刚强调了一些关于何时使用常见Http verbs要点