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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/904001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:16:40  来源:igfitidea点击:

Why use HTTP PUT and DELETE methods instead of POST?

ruby-on-railshttpdelete-method

提问by mipadi

 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"}

In web development I have done with other technologies, I only ever used GETand POSTmethods, but with RESTfulroutes in Rails, by default the PUTand DELETEmethods are used for the updateand destroyactions. What's the advantage or need for using PUTand DELETE? I assume these methods are just another way of doing POST- but why not just stick with POST?

在 web 开发中,我使用过其他技术,我只使用过GETandPOST方法,但是对于RESTfulRails 中的路由,默认情况下PUTandDELETE方法用于updateanddestroy操作。使用PUTand 有DELETE什么好处或需要?我认为这些方法只是另一种方式POST- 但为什么不坚持使用POST

回答by mipadi

The advantage is mostly semantic, and can also simplify URLs to an extent. The different HTTP methods map to different actions:

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

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

Then, in theory, you can use the sameURL, but interact with it using different methods; the method used to access the resource defines the actual type of operation.

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

In practice, though, most browsers only support HTTP GET and POST. Rails uses some "trickery" in HTML forms to act as though a PUT or DELETE request was sent, even though Rails is still using GET or POST for these methods. (This explains why you might not have used DELETE or PUT on other platforms.)

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

回答by Hank Gay

Here's the "methods" section of the HTTP 1.1 spec; it defines lots of methods, and they all have different benefits and tradeoffs. POSTis the most flexible, but the tradeoffs are numerous: it's not cacheable (so the rest of the internet can't help you scale), it isn't safe or idempotent so the client can't just resend it gets an error, and it is no longer clear exactly what you're trying to accomplish (because it's so flexible). I'm sure there are others but that ought to be sufficient. Given all that, if the HTTP spec defines a method that does exactly what you want your request to do, there's no reason to send a POSTinstead.

这是HTTP 1.1 规范“方法”部分;它定义了很多方法,它们都有不同的好处和权衡。POST是最灵活的,但要权衡很多:它不可缓存(因此互联网的其余部分无法帮助您扩展),它不安全或幂等,因此客户端不能仅重新发送它就会出错,并且不再清楚你想要完成什么(因为它太灵活了)。我敢肯定还有其他的,但这应该足够了。鉴于所有这些,如果 HTTP 规范定义了一个完全按照您的请求执行操作的方法,则没有理由发送一个POST来代替。

The reason POSTis so common is that, historically at least, web browsers only supported GETand POST. Since GETis defined to be safe and idempotent (even though many applications don't adhere to that), the only safeway to modify data was to send a POST. With the rise of AJAX and non-browser clients, that is no longer true.

原因POST如此普遍,至少从历史上看,Web 浏览器仅支持GETPOST. 由于GET被定义为安全和幂等的(即使许多应用程序不遵守这一点),修改数据的唯一安全方法是发送POST. 随着 AJAX 和非浏览器客户端的兴起,这不再是事实。

BTW, the mapping @mipadi gave is the standard mapping, but it isn't the only valid one. Amazon S3, for instance, uses PUTto create resources. The only reason to use POSTis if the client doesn't have sufficient knowledge to create the resource, e.g., you back your resources with a relational database and use artificial surrogate keys.

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

回答by Josh

That'd be kind of like asking why "delete" a file when you could just set its contents to zero bytes and the file system would just treat that as a delete. HTTP has supported verbs other than GET/POST forever but the way SOAP evolved kinda twisted the original meaning of those verbs. REST is a simpler, back to basics approach that uses the verbs as they were intended instead of inventing some new verb concept inside of the payload.

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

回答by Train

I just wanted to add something to the accepted answer because his definition of the http verbsare incorrect. They all have a spec which "should" be followed and you can create/update/delete with multiple http verbsbased on the specs.

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

I am going to highlight some of the important bits in the RFC 2616 by W3

我将重点介绍W3RFC 2616中的一些重要内容

I'm going to start with PUTbecause in my opinion it has the most confusion surrounding it.

我将开始,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
  • PUT is used for both create/update PUT updates by completely replacing the resource on the server with the resource sent in the request

For example

例如

You make this call to my api

你给我的api打这个电话

PUT        /api/person
{
     Name: John,
     email: [email protected]
}

my Server has this resource living on the server

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

{
     Name: Jane,
     email: [email protected]
}

Now my existing resource is completely replaced by what you sent over and this is what I have on my server.

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

{
     Name: John,
     email: [email protected]
}

So if you PUTand only send an email in the body

所以如果你PUT只在正文中发送一封电子邮件

PUT        /api/person
{
     email: [email protected]
}

My Server will completely replace the entity

我的服务器将完全替换实体

{
     Name: Jane,
     email: [email protected]
}

With

{
     email: [email protected]
}

And Name will be gone. Partial updates are for PATCHbut I use POSTfor that anyway.

而名字将消失。部分更新是为了,PATCHPOST无论如何我都用它。

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

It's just a fancy term and the basic definition of it is multiple identical requests are the same for a single request.

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

Example

例子

Suppose I PUTa file to api/fileif the origin server does not find that file it will create one. If it does find a file it will completely replace the old file with the one I sent over. This ensures that one file is ever created and updated.If no file exists and you call PUT5 times, the first time it creates a file then the other 4 times it replaces the file with what you send over. If you call a POST5 times to create it will create 5 files.

假设我PUT有一个文件,api/file如果源服务器没有找到该文件,它将创建一个。如果它确实找到了一个文件,它将用我发送的文件完全替换旧文件。这可确保创建和更新一个文件。如果不存在文件并且您调用了PUT5 次,第一次它会创建一个文件,然后其他 4 次它会用您发送的内容替换该文件。如果您调用 a POST5 次来创建,它将创建 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
  • 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

Those are the major points in when to use PUT

这些是何时使用 PUT 的要点

As far as POSTis concerned

至于POST关注

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

As I mentioned above there are a few key differences.

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

  • Post is more General. In what ways? some other examples include a gateway to other protocols, it could take the response and send it to some data handler out in the middle of yonder, or it can extend some sort of functionality.
  • Post doesn't have the restriction of "To the exact URI or notifiy" for examplePOSTcan append a resource to an existing collection and decide where it's stored.
  • 帖子比较一般。以什么方式?其他一些示例包括通往其他协议的网关,它可以接收响应并将其发送到中间的某个数据处理程序,或者它可以扩展某种功能。
  • Post 没有“到确切的 URI 或通知”的限制,例如POST可以将资源附加到现有集合并决定它的存储位置。

Now what about DeleteWhy don't I just POST?

现在我Delete为什么不POST呢?

When you DELETE, the server SHOULD NOTrespond with successunless you delete the resource or move it to an inaccessible location at the time the response is sent.

当你DELETE的服务器不应该有应对的成功,除非你删除该资源或将它移动到难以接近的位置在响应发送的时间

Why is that important? What if you call DELETEbut the resource has to go through "APPROVAL" before being deleted? If the delete can be rejected you can't send a successful error code and if you do follow the basic specs on this it's confusing to the caller. Just an example I'm sure you can think of many others.

为什么这很重要?如果你打电话DELETE但资源在被删除之前必须经过“批准”怎么办?如果删除可以被拒绝,您将无法发送成功的错误代码,并且如果您确实遵循了基本规范,这会让调用者感到困惑。只是一个例子,我相信你可以想到很多其他的。

I just highlighted some of the major points on when to use the common Http verbs

我只是强调了一些关于何时使用通用的要点 Http verbs