根据HTTP / 1.1规范:

POST方法用于请求源服务器接受请求中包含的实体作为Request-Line Request-URI标识的资源的新下属

换句话说, POST用于创建

PUT方法请求将封闭的实体存储在提供的Request-URI 。 如果Request-URI引用了已经存在的资源,则应将封闭的实体视为驻留在原始服务器上的实体的修改版本。 如果Request-URI没有指向现有资源,并且请求用户代理能够将该URI定义为新资源,则原始服务器可以使用该URI创建资源。”

也就是说, PUT用于创建或更新

那么,应该使用哪一个来创建资源? 还是需要同时支持两者?


#1楼

新答案(现在我对REST有了更好的了解):

从现在开始,PUT只是服务应使用哪些内容来呈现客户端标识的资源的表示; POST是关于服务从现在开始应包含(可能重复)的内容的声明,但取决于服务器如何识别该内容。

PUT x (如果x标识一个资源 ):“通过更换标识的资源内容x用我的内容。”

PUT x (如果x不能标识资源):“创建一个包含我的内容的新资源,并使用x进行标识。”

POST x :“存储我的内容并给我一个标识符,我可以用它来标识包含所述内容(可能与其他内容混合)的资源(旧的或新的)。所述资源应与x标识的资源相同或从属。” “Y的资源是从属于X的资源”是通常但不通过使Y X的子路径(例如,x =不一定实现/fooy = /foo/bar )和修改x的表示(S)'的资源以反映新资源的存在,例如具有指向y的资源的超链接和一些元数据。 只有后者才是良好设计的真正必要条件,因为URL在REST中是不透明的-您应该使用超媒体而不是客户端URL构造来遍历服务。

在REST中,不存在包含“内容”的资源。 我将“内容”称为服务用来一致地表示形式的数据。 它通常由数据库或文件(例如,图像文件)中的一些相关行组成。 服务的内容取决于将用户的内容转换为服务可以使用的内容,例如,将JSON有效负载转换为SQL语句。

原始答案(可能更容易阅读)

PUT /something (如果/something已经存在):“拿走/something ,然后用我给您的/something替换。”

PUT /something (如果/something还不存在):“拿走我给你的/something ,放在/something 。”

POST /something :“接受我给您的内容,并将它放在/something下的任何位置,只要您在完成后给我其URL。”


#2楼

POST就像将信件投递到邮箱或将电子邮件投递到电子邮件队列一样。 PUT就像将对象放在小孔或架子上的某个位置(它具有已知地址)时一样。

使用POST,您将发布到QUEUE或COLLECTION的地址。 使用PUT,您可以输入ITEM的地址。

PUT是幂等的。 您可以发送请求100次,这无关紧要。 POST不是幂等的。 如果您发送请求100次,您的邮政信箱将收到100封电子邮件或100封信。

一般规则:如果您知道商品的ID或名称,请使用PUT。 如果要由接收方分配项目的ID或名称,请使用POST。


#3楼

摘要:

创造:

可以通过以下方式同时使用PUT或POST执行:

在/ resources URI或collection下使用newResourceId作为标识符创建THE新资源。

 PUT /resources/<newResourceId> HTTP/1.1 

开机自检

在/ resources URI或collection下创建一个新资源。 通常,标识符由服务器返回。

 POST /resources HTTP/1.1 

更新:

只能通过以下方式通过PUT执行:

在/ resources URI或collection下,以现存资源为标识更新资源。

 PUT /resources/<existingResourceId> HTTP/1.1 

说明:

当与REST和URI一般打交道,你必须在左边具体权利 一般泛型通常称为集合 ,更具体的项目称为资源 。 请注意, 资源可以包含集合

例子:

<-通用-特定->

 URI: website.com/users/john website.com - whole site users - collection of users john - item of the collection, or a resource URI:website.com/users/john/posts/23 website.com - whole site users - collection of users john - item of the collection, or a resource posts - collection of posts from john 23 - post from john with identifier 23, also a resource 

使用POST时,您总是引用collection ,因此无论何时您说:

POST /users HTTP/1.1

您正在将新用户发布到用户 集合

如果继续尝试以下操作:

POST /users/john HTTP/1.1

它会起作用,但从语义上讲,您是在向用户 集合下的john 集合添加资源。

使用PUT后,您将引用资源或单个项目,可能在collection中 。 所以当你说:

PUT /users/john HTTP/1.1

您要告诉服务器更新,或者在用户 集合下创建john 资源 (如果不存在)。

规格:

让我强调一下规范的一些重要部分:

开机自检

POST方法用于请求源服务器接受请求中包含的实体作为请求行中Request-URI标识的资源的下属

因此,在collection上创建一个新资源

PUT方法请求将封闭的实体存储在提供的Request-URI下。 如果Request-URI引用了已经存在的资源,则应将封闭的实体视为驻留在原始服务器上的实体的修改版本 。 如果Request-URI 没有指向现有资源,并且请求用户代理能够将该URI定义为资源 ,则原始服务器可以使用该URI 创建资源。”

因此,根据资源的存在来创建或更新。

参考:

  • HTTP / 1.1规范
  • 维基百科-REST
  • 统一资源标识符(URI):通用语法和语义

#4楼

对于何时将HTTP POST与HTTP PUT方法用于REST服务似乎似乎总是有些困惑。 大多数开发人员将尝试将CRUD操作直接关联到HTTP方法。 我认为这是不正确的,并且不能简单地将CRUD概念与HTTP方法相关联。 那是:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

确实可以将CRUD操作的R(etrieve)和D(elete)分别直接映射到HTTP方法GET和DELETE。 但是,混乱之处在于C(reate)和U(update)操作。 在某些情况下,可以使用PUT进行创建,而在其他情况下,则需要POST。 歧义在于HTTP PUT方法与HTTP POST方法的定义。

根据HTTP 1.1规范,GET,HEAD,DELETE和PUT方法必须是幂等的,而POST方法不是幂等的。 也就是说,如果一个操作可以在一个资源上执行一次或多次并且始终返回该资源的相同状态,则该操作是幂等的。 非幂等操作可以将资源的修改状态从一个请求返回到另一个请求。 因此,在非幂等操作中,不能保证将收到资源的相同状态。

基于上述幂等定义,我对REST服务使用HTTP PUT方法与使用HTTP POST方法的比较是:在以下情况下使用HTTP PUT方法:

The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).

在两种情况下,这些操作都可以执行多次,并且结果相同。 也就是说,通过多次请求操作不会更改资源。 因此,这是真正的幂等运算。 在以下情况下使用HTTP POST方法:

The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.

结论

不要直接关联CRUD操作并将其映射到REST服务的HTTP方法。 HTTP PUT方法与HTTP POST方法的使用应基于该操作的幂等方面。 也就是说,如果该操作是幂等的,则使用HTTP PUT方法。 如果该操作不是幂等的,则使用HTTP POST方法。


#5楼

我将使用以下内容:

PUT是指由URI标识的资源。 在这种情况下,您将对其进行更新。 它是涉及资源的三个动词的一部分-删除并成为其他两个。

POST基本上是一种自由格式的消息,其含义是“带外”定义的。 如果可以将消息解释为在目录中添加资源,那可以,但是基本上,您需要了解要发送(发布)的消息,以了解资源将发生什么。


因为PUT和GET和DELETE是指资源,所以它们在定义上也是幂等的。

POST可以执行其他三个功能,但是请求的语义将在诸如缓存和代理之类的中介上丢失。 这也适用于在资源上提供安全性,因为帖子的URI不一定表示它要应用于的资源(尽管可以)。

PUT不一定要创建; 如果尚未创建资源,则该服务可能会出错,但否则将对其进行更新。 反之亦然-它可能创建资源,但不允许更新。 PUT唯一需要的就是指向一个特定的资源,而其有效载荷就是该资源的表示。 成功的PUT意味着(排除干扰),GET将检索相同的资源。


编辑:还有一件事-PUT可以创建,但是如果这样做,则ID必须是自然ID-也就是电子邮件地址。 这样,当您两次输入PUT时,第二个Put就是对第一个Put的更新。 这使其成为幂等的

如果生成了ID(例如,新的员工ID),则具有相同URL的第二个PUT将创建一条新记录,这违反了幂等规则。 在这种情况下,动词为POST,消息(不是资源)将使用此消息中定义的值来创建资源。


#6楼

是否使用PUT或POST在具有HTTP + REST API的服务器上创建资源的决定取决于谁拥有URL结构。 使客户知道或参与定义URL结构是类似于SOA产生的不良耦合的不必要耦合。 转义类型是REST如此流行的原因。 因此,使用的正确方法是POST。 该规则有一些例外,当客户端希望保留对其部署的资源的位置结构的控制权时,就会发生这些例外。 这种情况很少见,很可能意味着其他地方出了问题。

在这一点上,有人会争辩说,如果使用RESTful-URL ,则客户端确实知道资源的URL,因此可以接受PUT。 毕竟,这就是为什么规范的,规范化的,Ruby on Rails,Django URL很重要的原因,请看一下Twitter API……等等等等。 那些人需要了解没有Restful-URL之类的东西Roy Fielding自己指出

REST API不得定义固定的资源名称或层次结构(客户端和服务器的明显结合)。 服务器必须具有控制自己的名称空间的自由。 相反,允许服务器通过在媒体类型和链接关系中定义那些指令来指导客户端如何构造适当的URI(例如以HTML表单和URI模板完成)。 [此处失败表示客户端由于带外信息(例如,特定于域的标准)而采用了一种资源结构,该特定于域的标准在数据方面等同于RPC的功能耦合]。

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-超文本驱动

RESTful-URL的概念实际上违反了REST,因为服务器负责URL结构,应该自由决定如何使用它来避免耦合。 如果这使您感到困惑,您将了解自我发现对API设计的重要性。

使用POST创建资源需要进行设计考虑,因为POST不是幂等的。 这意味着多次重复POST并不能保证每次都具有相同的行为。 这使人们在不应该使用PUT来创建资源时感到恐惧。 他们知道这是错误的(POST是用于CREATE的),但他们还是这样做,因为他们不知道如何解决此问题。 在以下情况下证明了这种担忧:

  1. 客户端将新资源发布到服务器。
  2. 服务器处理该请求并发送响应。
  3. 客户端永远不会收到响应。
  4. 服务器未意识到客户端尚未收到响应。
  5. 客户端没有资源的URL(因此,PUT不是一个选项),并重复POST。
  6. POST不是幂等的,服务器…

第6步是人们通常对要做的事情感到困惑的地方。 但是,没有理由创建一个解决方案来解决此问题。 相反,可以按照RFC 2616中的指定使用HTTP,并且服务器会回复:

10.4.10 409冲突

由于与资源的当前状态存在冲突,因此无法完成请求。 仅在预期用户可能能够解决冲突并重新提交请求的情况下才允许使用此代码。 响应正文应包含足够的内容

供用户识别冲突源的信息。 理想情况下,响应实体应包括足够的信息供用户或用户代理解决问题。 但是,这可能是不可能的,也不是必需的。

响应PUT请求最有可能发生冲突。 例如,如果正在使用版本控制,并且正在PUT的实体包括对资源的更改,该更改与先前的(第三方)请求所做的更改冲突,则服务器可能会使用409响应来指示它无法完成请求。 在这种情况下,响应实体可能会以响应Content-Type定义的格式包含两个版本之间差异的列表。

回复状态码为409冲突是正确的方法,因为

  • 对具有与系统中已有资源匹配的ID的数据执行POST是“与资源的当前状态冲突”。
  • 由于重要的部分是让客户端了解服务器拥有的资源并采取适当的措施。 这是一个“期望用户能够解决冲突并重新提交请求的情况”。
  • 包含具有冲突ID的资源URL和资源的适当前提条件的响应将提供“足够的信息供用户或用户代理解决问题”,这是RFC 2616的理想情况。

基于RFC 7231版本的更新以替换2616

RFC 7231旨在替代2616,并在第4.3.3节中描述了POST的以下可能响应

如果处理POST的结果等同于现有资源的表示,则源服务器可以通过在位置字段中发送带有现有资源标识符的303(见其他)响应,将用户代理重定向到该资源。 这样做的好处是为用户代理提供了一个资源标识符,并通过一种更适合共享缓存的方法来传输表示,尽管如果用户代理尚未缓存表示,则要付出额外的请求。

现在可能很想在重复POST的情况下简单地返回303。 但是,事实恰恰相反。 仅当多个创建请求(创建不同的资源)返回相同的内容时,才返回303。 一个示例是“谢谢您提交请求消息”,客户端无需每次都重新下载。 RFC 7231在第4.2.2节中仍然保持POST不具有幂等性,并继续保持POST应该用于创建。

有关此的更多信息,请阅读本文 。


#7楼

这是一个简单的规则:

放置到URL的PUT应该用于更新或创建可位于该URL的资源。

到URL的POST应该用于更新或创建位于其他(“从属”)URL上的资源,或者不能通过HTTP找到的资源。


#8楼

原始服务器可以使用该URI创建资源

因此,您可以使用POST,并且可能(但不是必须)使用PUT创建资源。 您不必同时支持两者。 对我来说,POST就足够了。 因此,这是一个设计决策。

如您的报价所述,您使用PUT来创建没有分配给IRI的资源,并且无论如何都想创建一个资源。 例如, PUT /users/123/password通常用新PUT /users/123/password替换旧密码,但是如果尚不存在密码(例如,由新注册的用户或通过恢复被禁止的用户),则可以使用它来创建密码。


#9楼

尽管可能有一种不可知的描述方式,但它似乎与网站答案中的各种陈述相冲突。

让我们在这里非常清楚和直接。 如果您是使用Web API的.NET开发人员,则事实是(来自Microsoft API文档) http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web -api-that-supports-crud-operations :

1. PUT = UPDATE (/api/products/id)
2. MCSD Exams 2014 -  UPDATE = PUT, there are **NO** multiple answers for that question period.

当然,您可以“使用” POST进行更新,但是只要遵循给定框架为您制定的约定即可。 就我而言,它是.NET / Web API,因此PUT用于UPDATE无需争论。

我希望这对阅读带有Amazon和Sun / Java网站链接的所有注释的Microsoft开发人员有所帮助。


#10楼

  • POST到URL 服务器定义的URL上创建子资源
  • 放置到URL 客户端定义的 URL上完整地创建/替换资源
  • 对URL进行PATCH 更新会在该客户端定义的URL上更新资源的一部分

PUT和POST的相关规范是RFC 2616§9.5ff。

POST创建一个子资源 ,因此POST到/items创建一个位于/items资源下的资源。 例如。 /items/1 。 两次发送相同的邮包将创建两个资源。

PUT用于在客户端已知URL处创建或替换资源。

因此:在创建资源之前, PUT仅是CREATE的候选对象,在此客户端客户已经知道该URL。 例如。 /blogs/nigel/entry/when_to_use_post_vs_put作为标题用作资源密钥

如果已存在,则PUT将替换已知URL处的资源,因此两次发送相同的请求无效。 换句话说, 对PUT的调用是幂等的

RFC的内容如下:

POST和PUT请求之间的根本区别体现在Request-URI的不同含义上。 POST请求中的URI标识将处理封闭实体的资源。 该资源可能是一个数据接受过程,某个其他协议的网关或一个接受注释的单独实体。 相比之下,PUT请求中的URI标识请求所包含的实体-用户代理知道要使用的URI,并且服务器绝不能尝试将请求应用于其他资源。 如果服务器希望将请求应用于其他URI,

注意: PUT主要用于更新资源(通过整体替换它们),但是最近有一种趋势是使用PATCH来更新现有资源,因为PUT指定它将替换整个资源。 RFC 5789。

2018年更新 :可以避免使用PUT。 请参阅“没有PUT的REST”

使用“不带PUT的REST”技术,想法是迫使消费者发布新的“统一”请求资源。 如前所述,更改客户的邮寄地址是对新“ ChangeOfAddress”资源的POST,而不是具有不同邮寄地址字段值的“ Customer”资源的PUT。

摘自REST API设计-Thoughtworks的Prakash Subramaniam编写的资源建模

这迫使API避免多个客户端更新单个资源的状态转换问题,并与事件源和CQRS更好地匹配。 当工作异步完成时,发布转换并等待其应用似乎是适当的。


#11楼

在实践中,POST非常适合创建资源。 新创建资源的URL应该在Location响应头中返回。 PUT应该用于完全更新资源。 请理解,这些是设计RESTful API时的最佳实践。 这样的HTTP规范并不限制使用PUT / POST,而在创建/更新资源方面有一些限制。 请参阅http://techoctave.com/c7/posts/71-twitter-rest-api-dissected ,其中总结了最佳做法。


#12楼

您可以在网络上找到这样的断言:

  • POST应该用于创建资源,而PUT应该用于修改资源
  • 应该使用PUT创建资源,并使用POST修改资源

两者都不对。


更好的是根据操作的幂等性在PUT和POST之间进行选择。

PUT意味着放置资源-用另一件事完全替换给定URL上可用的任何内容。 根据定义,PUT是幂等的。 随意执行多次,结果是相同的。 x=5是幂等的。 您可以放置​​一个资源,无论它先前是否存在(例如,创建或更新)!

POST更新资源,添加辅助资源或引起更改。 POST不是幂等的,因为x++不是幂等的。


通过此参数,PUT用于在您知道要创建的事物的URL时进行创建。 当您知道要创建的事物类别的“工厂”或管理者的URL时,可以使用POST进行创建。

所以:

POST /expense-report

要么:

PUT  /expense-report/10929

#13楼

两者都用于客户端到服务器之间的数据传输,但是它们之间存在细微的差异,它们是:

比喻:

  • 放置 ,即放在原处。
  • 邮局以邮寄方式发送邮件。

社交媒体/网络类比:

  • 发表于社交媒体:当我们发布的消息,它创造了新的岗位。
  • 放入 (即编辑)我们已经发布的消息。

#14楼

对该主题不熟悉的读者将不知疲倦地讨论您该做什么,并且相对缺乏经验教训。 我想,REST是比SOAP更为“优选”的事实,这是从经验中学到的高级知识,但是,天哪,我们一定已经取得了进步吗? 是2016年。罗伊(Roy)的论文是2000年。我们开发了什么? 它有趣吗? 整合起来容易吗? 支持? 它能应付智能手机和不稳定的移动连接的兴起吗?

据我说,现实生活中的网络是不可靠的。 请求超时。 连接被重置。 网络一次会中断数小时或数天。 火车与移动用户一起进入隧道。 对于任何给定的请求(在本次讨论中都会偶尔承认),该请求可能会顺其自然地掉入水中,或者响应可能会在其回程中掉入水中。 在这种情况下,直接针对实质性资源发出PUT,POST和DELETE请求总是让我感到有些野蛮和天真。

HTTP不会做任何事情来确保请求响应的可靠完成,这很好,因为这恰好是网络感知应用程序的工作。 开发这样的应用程序,您可以跳过箍使用PUT而不是POST,如果检测到重复的请求,则可以通过更多箍在服务器上发出某种错误。 然后,回到客户端,您就不得不跳过去解释这些错误,重新获取,重新验证并重新发布。

或者,您可以执行以下操作 :将不安全的请求视为短暂的单用户资源(我们称其为操作)。 客户端请求对该实体资源执行新的“操作”,同时对该资源执行空POST。 POST仅用于此目的。 一旦安全地拥有了刚创建的动作的URI,客户端就会将不安全的请求放到动作URI, 而不是目标资源 。 解决该问题并更新“真实”资源完全是您API的工作,并且在这里与不可靠的网络分离。

服务器进行业务,返回响应并将其存储在约定的操作URI中 。 如果发生任何错误,客户端将重复该请求(自然行为!),如果服务器已经看到请求,则它将重复存储的响应, 并且不执行其他任何操作

您将很快发现Promise与Promise的相似之处:我们在做任何事情之前都会为结果创建并返回占位符。 就像承诺一样,动作可以一次成功或失败,但是其结果可以重复获取。

最重要的是,我们使发送和接收应用程序有机会将唯一标识的操作与各自环境中的唯一性相关联。 我们可以开始要求并强制执行!来自客户的负责任的行为:尽可能多地重复您的请求,但是直到您拥有现有请求的明确结果后,再进行新操作。

这样,许多棘手的问题就消失了。 重复的插入请求不会创建重复项,并且只有拥有数据后我们才创建真实资源。 (数据库列可以保持不可为空)。 重复的更新请求不会遇到不兼容的状态,也不会覆盖后续的更改。 客户可以出于任何原因(客户崩溃,响应丢失等)来(重新)获取和无缝处理原始确认。

连续的删除请求可以查看并处理原始确认,而不会遇到404错误。 如果事情花的时间比预期的长,我们可以临时做出回应,我们可以让客户检查确定的结果。 这种模式最好的部分是其功夫(熊猫)属性。 我们有一个弱点,即客户倾向于在他们不理解响应的任何时候重复请求,并将其转变为一种优势 :-)

在告诉我这不是RESTful之前,请考虑尊重REST原则的多种方式。 客户端不构造URL。 该API保持可发现性,尽管语义上有少许变化。 适当使用HTTP动词。 如果您认为这是实施的巨大变化,我可以从经验中告诉您,事实并非如此。

如果您认为要存储大量数据,那么我们来谈一谈卷:一个典型的更新确认只有千分之一字节。 HTTP当前给您一两分钟的时间做出明确的响应。 即使您只存储一周的操作,客户也有足够的机会赶上。 如果容量很大,则可能需要专用的符合酸标准的键值存储或内存解决方案。


#15楼

如果您熟悉数据库操作,则有

  1. 选择
  2. 插入
  3. 更新资料
  4. 删除
  5. 合并(如果已存在则更新,否则插入)

我使用PUT进行合并和更新操作,并使用POST进行插入。


#16楼

简而言之:

PUT是幂等的,如果一次或多次执行相同的操作,则资源状态将相同。

POST是非幂等的,与执行一次相比,如果多次执行该操作,资源状态可能会有所不同。

类比数据库查询

你能想到的类似“UPDATE STUDENT SET地址=‘ABC’其中id =” 123" ;

POST您可以想到类似“ INSERT INTO STUDENT(name,address)VALUES(“ abc”,“ xyzzz”);

学生ID是自动生成的。

使用PUT,如果同一查询多次执行或一次执行,则STUDENT表状态保持不变。

对于POST,如果多次执行相同的查询,则会在数据库中创建多个Student记录,并且每次执行“ INSERT”查询时数据库状态都会更改。

注意: PUT需要一个需要更新的资源位置(已有资源),而POST则不需要。 因此,直观地讲,POST是用于创建新资源的,而PUT是更新现有资源所必需的。

有些人可能会想到可以使用POST执行更新。 没有硬性规定使用哪个进行更新或使用哪个进行创建。 同样,这些都是惯例,从直觉上讲,我倾向于上述推理,并遵循它。


#17楼

我以一种非常简单的方式,以Facebook时间轴为例。

情况1:在时间轴上发布内容时,这是一个全新的条目。 因此,在这种情况下,他们使用POST方法,因为POST方法是非幂等的。

情况2:如果您的朋友第一次评论您的帖子,这也会在数据库中创建一个新条目,因此将使用POST方法。

情况3:如果您的朋友编辑他的评论,在这种情况下,他们有一个评论ID,因此他们将更新现有评论,而不是在数据库中创建新条目。 因此,对于这种类型的操作,请使用PUT方法,因为它是幂等的。*

在一行中,使用POST在数据库中添加新条目 ,并使用PUT在数据库中更新某些内容。


#18楼

大多数时候,您将像这样使用它们:

  • 发布一个资源到一个集合
  • 放置由collection /:id标识的资源

例如:

  • POST /项目
  • PUT /项目/ 1234

在这两种情况下,请求正文都包含要创建或更新的资源的数据。 从路由名称可以明显看出POST不是幂等的(如果调用3次,它将创建3个对象),但是PUT是幂等的(如果调用3次,结果是相同的)。 PUT通常用于“ upsert”操作(创建或更新),但是如果您只想使用它来进行修改,则始终可以返回404错误。

请注意,POST在集合中“创建”了一个新元素,PUT在给定的URL上“替换”了一个元素,但是使用PUT进行部分修改是一种非常普遍的做法,即仅使用它来更新现有资源并仅修改主体中包含的字段(忽略其他字段)。 从技术上讲,这是不正确的,如果您想成为REST纯粹主义者,则PUT应该替换整个资源,并且应该使用PATCH进行部分更新。 我个人并不关心行为在所有API端点上是否清晰一致。

请记住,REST是一组使您的API保持简单的约定和准则。 如果最终只是为了检查“ RESTfull”复选框而遇到了一个复杂的解决方法,那么您将无法达到目的;)


#19楼

简短答案:

简单的经验法则:使用POST创建,使用PUT更新。

长答案:

开机自检:

  • POST用于将数据发送到服务器。
  • 当资源的URL未知时很有用

放:

  • PUT用于将状态传输到服务器
  • 当知道资源的URL时很有用

更长的答案:

要理解它,我们需要质疑为什么需要PUT,PUT试图解决POST不能解决的问题是什么。

从REST架构的角度来看,没有任何关系。 如果没有PUT,我们也可以生活。 但是从客户开发人员的角度来看,这使他/她的生活变得简单得多。

在进行PUT之前,客户端无法直接知道服务器生成的URL,或者它是否全部生成了URL,也无法知道要发送到服务器的数据是否已更新。 PUT减轻了开发人员的所有这些麻烦。 PUT是幂等的,PUT处理竞争条件,并且PUT让客户端选择URL。


#20楼

我想补充一下我的“务实”建议。 当您知道可以检索保存的对象的“ id”时,请使用PUT。 如果您需要返回数据库生成的ID以供您以后进行查找或更新,则使用PUT不能很好地工作。

因此:要保存现有用户,或保存客户端生成ID的用户,并已验证ID是唯一的:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.comGET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

否则,使用POST最初创建对象,然后使用PUT更新对象:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.comPUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

#21楼

除了其他人建议的差异外,我还要添加一个。

POST方法中,您可以在form-data发送正文参数

PUT方法中,您必须以x-www-form-urlencoded发送身体参数

标头Content-Type:application/x-www-form-urlencoded

因此,您不能使用PUT方法发送文件或多部分数据

编辑

内容类型“ application / x-www-form-urlencoded”对于发送大量二进制数据或包含非ASCII字符的文本效率不高。 内容类型“ multipart / form-data”应用于提交包含文件,非ASCII数据和二进制数据的表单。

这意味着如果您必须提交

文件,非ASCII数据和二进制数据

您应该使用POST方法


#22楼

冒着重述已经说过的风险的危险,记住PUT意味着客户端在创建资源时控制URL最终要成为的样子似乎很重要。 因此,在PUTPOST之间进行选择的一部分将是您可以信任客户端提供多少与您的URL方案一致的正确的,标准化的URL

当您不能完全信任客户端做正确的事时,使用POST创建新项目,然后在响应中将URL发送回客户端会更合适。


#23楼

使用POST创建,并使用PUT更新。 无论如何,这就是Ruby on Rails的做法。

PUT    /items/1      #=> update
POST   /items        #=> create

#24楼

总体:

PUT和POST均可用于创建。

您必须问“您要对该动作执行什么操作?” 来区分您应该使用的内容。 假设您正在设计一个用于询问问题的API。 如果要使用POST,则可以对一系列问题进行处理。 如果要使用PUT,则可以对特定问题进行操作。

两者都可以使用,因此在RESTful设计中应该使用哪一个:

您不需要同时支持PUT和POST。

使用哪种取决于您自己。 但请记住,请根据您在请求中引用的对象来使用正确的对象。

一些注意事项:

  • 您是否命名您明确创建的URL对象,还是由服务器决定? 如果命名,请使用PUT。 如果让服务器决定,则使用POST。
  • PUT是幂等的,因此,如果将一个对象两次放置,则不会起作用。 这是一个很好的属性,所以我会尽可能使用PUT。
  • 您可以使用具有相同对象URL的PUT更新或创建资源
  • 使用POST,您可以同时收到2个请求,以对URL进行修改,它们可能会更新对象的不同部分。

一个例子:

我写了以下内容作为对此的另一个答案 :

开机自检:

用于修改和更新资源

 POST /questions/<existing_question> HTTP/1.1 Host: www.example.com/ 

请注意以下是错误:

 POST /questions/<new_question> HTTP/1.1 Host: www.example.com/ 

如果尚未创建URL,则在指定名称时不应使用POST来创建URL。 这将导致“找不到资源”错误,因为<new_question>还不存在。 您应该先在服务器上放置<new_question>资源。

您可以执行以下操作来使用POST创建资源:

 POST /questions HTTP/1.1 Host: www.example.com/ 

请注意,在这种情况下,未指定资源名称,新对象的URL路径将返回给您。

放:

用于创建资源或覆盖它。 当您指定资源时,新的URL。

对于新资源:

 PUT /questions/<new_question> HTTP/1.1 Host: www.example.com/ 

覆盖现有资源:

 PUT /questions/<existing_question> HTTP/1.1 Host: www.example.com/ 

此外,更简洁一点的是RFC 7231第4.3.4节PUT状态(添加了强调),

4.3.4。

PUT方法请求created目标资源的状态或replaced为请求消息有效负载中包含的表示形式所定义的状态。


#25楼

REST是一个非常高级的概念。 实际上,它甚至根本没有提到HTTP!

如果您对如何在HTTP中实现REST存有疑问,可以随时查看Atom发布协议(AtomPub)规范。 AtomPub是使用HTTP编写RESTful Web服务的标准,该标准是由许多HTTP和REST专家开发的,并由REST的发明者和HTTP的(共同)发明者Roy Fielding提出了一些建议。

实际上,您甚至可以直接使用AtomPub。 尽管它来自博客社区,但绝不限于博客:它是用于通过HTTP与任意资源(嵌套)的任意资源的RESTful交互的通用协议。 如果您可以将应用程序表示为资源的嵌套集合,则可以只使用AtomPub,而不必担心要使用PUT还是POST,要返回的HTTP状态代码以及所有这些详细信息。

这是AtomPub关于资源创建的内容(第9.2节):

要将成员添加到集合,客户端将POST请求发送到集合的URI。


#26楼

POST的意思是“新建”,如“此处是创建用户的输入,请为我创建”。

PUT的意思是“插入,如果已经存在则替换”,如“这是用户5的数据”中所述。

由于您尚不知道用户的URL,因此您将其发布到example.com/users,因此您希望服务器创建它。

由于您要替换/创建特定用户,因此将其放入example.com/users/id。

使用相同的数据两次发布意味着创建两个具有不同ID的相同用户。 使用相同的数据两次输入将首先创建用户,第二次将其更新为相同状态(无更改)。 由于无论执行多少次PUT之后,您最终都会处于相同的状态,因此每次都被称为“同等有效”-等幂。 这对于自动重试请求很有用。 按下浏览器上的“后退”按钮时,不再“确定要重新发送”。

一般建议是,当您需要服务器控制资源的URL生成时,请使用POST。 否则使用PUT。 在开机自检中优先使用PUT。


#27楼

语义是不同的,因为“ PUT”就像“ GET”一样是幂等的-意思是,您可以多次重复相同的精确PUT请求,结果就像只执行一次一样。

我将描述我认为使用最广泛,最有用的约定:

当您将资源放在特定URL处时,会发生的情况是应将其保存在该URL或类似的行上。

当您发布到特定URL的资源时,通常会将相关信息发布到该URL。 这意味着URL上的资源已经存在。

例如,当您要创建新的流时,可以将其放置到某个URL。 但是,当您想要将消息发布到现有流时,可以将其发布到其URL。

至于修改流的属性,可以使用PUT或POST完成。 基本上,仅当操作是幂等时才使用“ PUT”-否则使用POST。

但是请注意,并非所有现代浏览器都支持GET或POST以外的HTTP动词。


#28楼

我喜欢这个建议,来自RFC 2616的PUT定义 :

POST和PUT请求之间的根本区别体现在Request-URI的不同含义上。 POST请求中的URI标识将处理封闭实体的资源。 该资源可能是一个数据接受过程,某个其他协议的网关或一个接受注释的单独实体。 相比之下,PUT请求中的URI标识请求所包含的实体-用户代理知道要使用的URI,并且服务器绝不能尝试将请求应用于其他资源。

这与此处的其他建议相矛盾,即PUT最好应用于已经具有名称的资源,而POST对于在现有资源下创建新对象(并让服务器命名)非常有用。

我将其解释为对PUT的幂等要求,以表示:

  • POST非常适合在集合下创建新对象(并且create不必是幂等的)
  • PUT非常适合更新现有对象(并且更新必须是幂等的)
  • POST还可以用于对现有对象进行非幂等更新(特别是在不指定整个对象的情况下更改对象的一部分)-如果您考虑一下,创建集合的新成员实际上是这种情况的特例从集合的角度进行更新)
  • 当且仅当您允许客户端命名资源时,PUT还可用于创建。 但是由于REST客户端不应该对URL结构进行假设,因此就本来打算而言,这样做就少了。

#29楼

最重要的考虑因素是可靠性 。 如果POST消息丢失,则系统状态不确定。 自动恢复是不可能的。 对于PUT消息,只有在第一次成功重试之前,状态才是未定义的。

例如,用POST创建信用卡交易可能不是一个好主意。

如果您在资源上碰巧有自动生成的URI,则仍然可以通过将生成的URI(指向空资源)传递给客户端来使用PUT。

其他一些注意事项:

  • POST使整个包含资源的缓存副本无效(更好的一致性)
  • POST响应时,PUT响应不可缓存(需要Content-Location和到期)
  • Java ME,较旧的浏览器,防火墙不支持PUT

#30楼

Ruby on Rails 4.0将使用“ PATCH”方法而不是PUT进行部分更新。

RFC 5789说到PATCH(自1995年起):

需要一种新方法来提高互操作性并防止错误。 已经定义了PUT方法以使用全新的主体覆盖资源,并且不能重用它来进行部分更改。 否则,代理和缓存,甚至客户端和服务器,可能会对操作结果感到困惑。 POST已被使用,但是没有广泛的互操作性(其中之一,没有发现补丁格式支持的标准方法)。 早期的HTTP规范中提到了PATCH,但尚未完全定义。

“ Edge Rails:PATCH是用于更新的新的主要HTTP方法 ”。

REST中的PUT与POST相关推荐

  1. GNU Make 使用手册(于凤昌中译版)

    GNU Make 使用手册(中译版) 翻译:于凤昌 GNU make Version 3.79 April 2000 Richard M. Stallman and Roland McGrath 1 ...

  2. 面试:第十二章:所有总结

    Java基础 java基本类型哪些,所占字节 byte :1个字节 short :2个字节 char :2个字节 int :4个字节 long :8个字节 float :4个字节 double :8个 ...

  3. linux内核分析(转自某位大哥网上的笔记)

    启动 当PC启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处的代码,也就是ROM-BIOS起始位置的代码.BIOS先进行一系列的系统自检,然后初始化位于地址0的中断 ...

  4. golang通过RSA算法生成token,go从配置文件中注入密钥文件,go从文件中读取密钥文件,go RSA算法下token生成与解析;go java token共用

    RSA算法 token生成与解析 本文演示两种方式,一种是把密钥文件放在配置文件中,一种是把密钥文件本身放入项目或者容器中. 下面两种的区别在于私钥公钥的初始化, init方法,需要哪种取哪种. 通过 ...

  5. 总结一下在使用某里云服务器的过程中出现过的一些问题

    此文总结在使用阿里云的过程中出现过的问题   想起来就记录一下 本人为言行负责! 海内选择腾讯华为,共勉! k8s不同命名空间的配置文件串掉了 k8s集群服务器购买上后,无法使用外网.连续购买了4台然 ...

  6. Kubernetes 中 设置pod不部署在同一台节点上

    在k8s中,节点的调度主要由亲和性和污点来进行控制的.   而在亲和性部分由分为了节点亲和性和节点反亲和性.   节点亲和性是指在pod部署时,尽量(软策略)或者必须满足(硬策略)部署在某些节点上. ...

  7. 在Dockerfile中设置G1垃圾回收器参数

    在Dockerfile中设置G1垃圾回收器参数 ENV JAVA_OPTS="\ -server \ -XX:SurvivorRatio=8 \ -XX:+DisableExplicitGC ...

  8. 在kotlin companion object中读取Bean,注入Bean对象

    在kotlin companion object中读取Bean,注入Bean对象 在使用kotlin时,或多或少地会使用到一些公共组件,如 http. mongo. redis相关的组件.   使用组 ...

  9. 在k8s中使用gradle构建java web项目镜像Dockerfile

    在k8s中使用gradle构建java web项目镜像Dockerfile FROM gradle:6-jdk8 AS build COPY --chown=gradle:gradle . /home ...

  10. 数据库中自定义排序规则,Mysql中自定义字段排序规则,Oracle中自定义字段排序规则,decode函数的用法,field函数的用法

    数据库中自定义排序 场景:有一张banner表,表中有一个status字段,有0, 1, 2三个状态位,我想要 1,0,2的自定义排序(这里是重点),然后再进行之上对sequence字段进行二次排序( ...

最新文章

  1. HIbernate——hibernate中的各种查询
  2. 高可用集群中的选举机制
  3. 初步了解超图官网提供的应用程序
  4. python中options设置_如何使用ChromeOptions在Python selenium中禁用CSS
  5. 【机器学习基础】数学推导+纯Python实现机器学习算法28:CRF条件随机场
  6. POJ - 2348 Euclid's Game(博弈)
  7. matlab 三维点 边界曲面,不用matlab如何从散点数据绘制极坐标三维曲面图?
  8. android关闭人脸检测功能,【Android知识】录像预览模式下打开人脸检测
  9. 简要增量式PI控制器
  10. dataframe画图
  11. PMP考试计算公式汇总
  12. linux底层把值传给上层,Android上层如何调用一个底层函数
  13. 视频格式怎么转换,将mp4格式转为mov格式
  14. BitBlt C++中BitBlt如何使用详解
  15. 【Java】文如何制作帮助文档
  16. android 分享wifi app下载安装,WiFi共享精灵下载
  17. 约瑟夫环的c语言描述
  18. 风光互补路灯实验,风光互补发电系统,智能型路灯,QY-T12
  19. 计算机网络安全等级可以划分为几级,网络安全级别划分为几个等级?
  20. visio中公式太小_冲压模具冲床吨位计算公式、实例分析,设计师值得一看

热门文章

  1. android gridview 停止滚动
  2. Android 10.0 系统启动之SystemServer进程-[Android取经之路]
  3. Android8.0恢复出厂设置失败-BroadcastQueue: Background execution not allowed
  4. com.android.builder.packaging.DuplicateFileException
  5. calendar获取月份少一个月_6月份,花园小学、铁岭小学等哈尔滨南岗校区部分二手房量价齐涨...
  6. linux日常运维手册_Linux日常运维上传下载工具lrzsz
  7. day002-HTML知识点总结:浏览器兼容性之指定IE浏览器使用chrome内核渲染页面
  8. Spring的qualifier标签
  9. apache rewrite规则详解
  10. NSURLSession使用说明及后台工作流程分析