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

时间:2009-05-24 15:30:06

标签: ruby-on-rails http delete-method

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?

4 个答案:

答案 0 :(得分:51)

优势主要是语义,也可以在一定程度上简化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。)

答案 1 :(得分:9)

这是"methods" section of the HTTP 1.1 spec;它定义了许多方法,它们都有不同的好处和权衡。 POST是最灵活的,但权衡很多:它不可缓存(因此互联网的其余部分无法帮助您扩展),它不安全或不是幂等因此客户端不能只重新发送它得到一个错误,它不再清楚你要完成什么(因为它是如此灵活)。我确信还有其他人,但这应该足够了。鉴于这一点,如果HTTP规范定义的方法完全符合您的要求,那么就没有理由发送POST

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

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

答案 2 :(得分:7)

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

答案 3 :(得分:3)

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

我将重点介绍RFC 2616 by W3

中的一些重要部分

我将从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.

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

实施例

假设我PUT文件到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...

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

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

现在呢Delete为什么我不只是POST

当您DELETE时,服务器不应成功回复,除非您删除资源或将其移至无法访问的位置响应已发送

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

我刚刚强调了何时使用公共Http verbs

的一些要点