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

时间:2022-09-25 14:43:01
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 work I have done with other technologies I only ever used GET and POST methods. But with RESTful routes in Rails, by default the PUT and DELETE methods are used for the update and destroy actions. What's the advantage or need for using PUT and DELETE? I assume these methods are just another way of doing POST - but why not just stick with POST?

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

4 个解决方案

#1


47  

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 same URL, 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。)

#2


8  

Here's the "methods" section of the HTTP 1.1 spec; it defines lots of methods, and they all have different benefits and tradeoffs. POST is 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 POST instead.

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

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

POST很常见的原因是,至少在历史上,Web浏览器只支持GET和POST。由于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 PUT to create resources. The only reason to use POST is 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的唯一原因是客户端没有足够的知识来创建资源,例如,您使用关系数据库备份资源并使用人工代理键​​。

#3


6  

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是一种更简单的回归基础方法,它使用动词,而不是在有效载荷内部发明一些新的动词概念。

#4


0  

I just wanted to add something to the accepted answer because it's too broad and a very old answer.

我只想在接受的答案中添加一些东西,因为它太宽泛而且答案很古老。

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

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

I'm going to start with PUT because 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用于通过使用请求中发送的资源完全替换服务器上的资源来创建/更新PUT更新

For example

例如

You make this call to my api

你打电话给我的api

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

my Server has this resource living on the server

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

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

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

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

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

So if you PUT and only send an email in the body

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

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

My Server will completely replace the entity

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

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

With

{
     email: jdoe@hra.com
}

And Name will be gone. Partial updates are for PATCH but I use POST for that anyway.

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

  • One of the main reasons why we create/update with put is because it is idempotent.
  • 我们使用put创建/更新的一个主要原因是因为它是幂等的。

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 PUT a file to api/file if 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 PUT 5 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 POST 5 times to create it will create 5 files.

假设我将文件输出到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
  • 你投入到那个确切的URI。如果不这样做,则必须向用户发送301(永久移动),然后允许选择是否重定向请求。大多数情况下,您PUT的服务器通常托管资源并负责更新它

Those are the major points in when to use PUT

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

As far as POST is concerned

就POST而言

  • 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 examplePOST can append a resource to an existing collection and decide where it's stored.
  • Post没有“To the exact URI or notifiy”的限制,例如,POST可以将资源附加到现有集合并确定它的存储位置。

Now what about Delete Why don't I just POST?

那么删除为什么我不只是POST?

When you DELETE, the server SHOULD NOT respond with success unless you delete the resource or move it to an inaccessible location at the time the response is sent.

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

Why is that important? What if you call DELETE but 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但资源在被删除之前必须通过“APPROVAL”怎么办?如果可以拒绝删除,则无法发送成功的错误代码,如果您遵循此基本规范,则会使调用者感到困惑。举个例子,我相信你能想到很多其他人。

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

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

#1


47  

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 same URL, 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。)

#2


8  

Here's the "methods" section of the HTTP 1.1 spec; it defines lots of methods, and they all have different benefits and tradeoffs. POST is 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 POST instead.

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

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

POST很常见的原因是,至少在历史上,Web浏览器只支持GET和POST。由于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 PUT to create resources. The only reason to use POST is 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的唯一原因是客户端没有足够的知识来创建资源,例如,您使用关系数据库备份资源并使用人工代理键​​。

#3


6  

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是一种更简单的回归基础方法,它使用动词,而不是在有效载荷内部发明一些新的动词概念。

#4


0  

I just wanted to add something to the accepted answer because it's too broad and a very old answer.

我只想在接受的答案中添加一些东西,因为它太宽泛而且答案很古老。

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

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

I'm going to start with PUT because 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用于通过使用请求中发送的资源完全替换服务器上的资源来创建/更新PUT更新

For example

例如

You make this call to my api

你打电话给我的api

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

my Server has this resource living on the server

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

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

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

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

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

So if you PUT and only send an email in the body

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

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

My Server will completely replace the entity

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

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

With

{
     email: jdoe@hra.com
}

And Name will be gone. Partial updates are for PATCH but I use POST for that anyway.

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

  • One of the main reasons why we create/update with put is because it is idempotent.
  • 我们使用put创建/更新的一个主要原因是因为它是幂等的。

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 PUT a file to api/file if 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 PUT 5 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 POST 5 times to create it will create 5 files.

假设我将文件输出到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
  • 你投入到那个确切的URI。如果不这样做,则必须向用户发送301(永久移动),然后允许选择是否重定向请求。大多数情况下,您PUT的服务器通常托管资源并负责更新它

Those are the major points in when to use PUT

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

As far as POST is concerned

就POST而言

  • 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 examplePOST can append a resource to an existing collection and decide where it's stored.
  • Post没有“To the exact URI or notifiy”的限制,例如,POST可以将资源附加到现有集合并确定它的存储位置。

Now what about Delete Why don't I just POST?

那么删除为什么我不只是POST?

When you DELETE, the server SHOULD NOT respond with success unless you delete the resource or move it to an inaccessible location at the time the response is sent.

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

Why is that important? What if you call DELETE but 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但资源在被删除之前必须通过“APPROVAL”怎么办?如果可以拒绝删除,则无法发送成功的错误代码,如果您遵循此基本规范,则会使调用者感到困惑。举个例子,我相信你能想到很多其他人。

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

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