当前位置:  开发笔记 > 编程语言 > 正文

REST中的PUT与POST

如何解决《REST中的PUT与POST》经验,为你挑选了30个好方法。

根据HTTP/1.1规范:

POST方法用来请求原始服务器接受被附在请求由标识的资源的新下属实体Request-URIRequest-Line

换句话说,POST用于创建.

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

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

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



1> Brian R. Bon..:

总体:

PUT和POST都可以用于创建.

你必须问"你在做什么动作?" 区分你应该使用的东西.我们假设您正在设计一个用于提问的API.如果您想使用POST,那么您可以将其添加到问题列表中.如果你想使用PUT那么你会对特定问题这样做.

两者都可以使用,所以我应该在我的RESTful设计中使用哪一个:

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

使用哪个由您自己决定.但请记住使用正确的,具体取决于您在请求中引用的对象.

一些考虑:

您是否明确指定了您创建的URL对象,还是让服务器决定?如果您为它们命名,则使用PUT.如果您让服务器决定然后使用POST.

PUT是幂等的,所以如果你将对象PUT两次,它就没有效果.这是一个很好的属性,所以我会尽可能使用PUT.

您可以使用具有相同对象URL的PUT更新或创建资源

使用POST,您可以同时处理2个请求,对URL进行修改,并且可以更新对象的不同部分.

一个例子:

我写了以下作为SO的另一个答案的一部分:

POST:

用于修改和更新资源

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

请注意以下是一个错误:

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

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

你可以做这样的事情来使用POST创建资源:

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

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

放:

用于创建资源或覆盖它.在指定资源新URL时.

对于新资源:

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

要覆盖现有资源:

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


我认为人们不能强调PUT是幂等的事实:如果网络拙劣并且客户端不确定他的请求是否通过,它可以发送它第二(或第100)时间,并且它由HTTP规范,这与发送一次具有完全相同的效果.
如果我没有弄错的话,我们应该强调的是PUT被*定义为幂等的.您仍然必须以PUT行为正确的方式编写服务器,是吗?也许最好说"PUT导致运输假设幂等,这可能会影响运输的行为,例如缓存."
@JörgWMittagEmplempotence标语?怎么样"发送和发送我的朋友,最终没有任何区别."
@JörgWMittag:没必要.如果请求在此期间被修改(第二次被其他用户或第一个请求本身通过),则第二次可以返回409 Conflict或者其他内容.
将它们视为:PUT =插入或更新; POST =插入.因此,当您进行两次PUT时 - 您获得一条新记录,当您执行两次POST时 - 您将获得两条新记录.
如果客户端关心资源的名称,PUT应仅用于创建资源.关心资源名称的客户表示耦合.耦合是不良做法的结果.因此,请使用POST.如果担心有两次使用POST创建资源(因为它不是幂等的),请阅读[此答案](http://stackoverflow.com/questions/630453/put-vs-post-in-rest/19670755#19670755) .
为了使事情更清楚,可能有一个想法是添加该示例应该返回错误:PUT/questions HTTP/1.1 Host:wahteverblahblah.com
**修改和更新**有什么区别
有人可以详细说明这句话."通过POST,您可以同时处理2个请求,对URL进行修改,并且可以更新对象的不同部分." 请解释为什么这适用于POST而不是PUT?
我认为定义没有区别.409即使客户提出第一个请求,冲突也可能是结果.无论如何,它应该调查问题.
我是第二个,@ MartinBrown ......实际上,你的观点对我来说非常有启发性.现在的答案已经太棒了,但是,不要误会我的意思!
您应该使用PATCH来更新实体,PUT来插入实体,DELETE来删除/删除实体,使用POST来做其他事情,比如提交表单数据类型请求.
作者的说法不是可以使用POST来修改/更新吗?例如,他正在使用POST / questions / <existing_question>,这意味着POST请求知道资源的位置,即<existing_question>,但这意味着POST显示“幂等行为”,无论有多少每当我们发出此请求时,将在服务器上访问相同的资源(`<existing_question>`),这是不正确的,因为POST应该被认为是“非幂等”,这意味着每次调用此命令时,它都应该更改状态服务器。

2> Cheeso..:

你可以在网上找到断言

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


我同意,无论在哪里有幂等性,它都应该胜过任何其他问题,因为错误会导致许多意想不到的错误.
@Schneider POST可以创建一个辅助资源; 因此,您可以POST到收集,例如**POST /费用报告**,它会在您的服务器上创建与您发送的请求数量一样多的实体(费用报告),即使它们完全相似.可以将其视为在DB表(/ expense-reports)中使用自动递增的主键插入相同的行.数据保持不变,密钥(在这种情况下为URI)由服务器生成,并且对于每个其他插入(请求)都不同.因此,POST效果**可以是幂等的,但也可能****.因此,POST不是**幂等的.
@Schneider,在这种情况下,你的服务器正在做出额外的努力以保证幂等性,但它并没有宣传它.如果用户尝试重新加载此类POST请求,浏览器仍会警告用户.
如果POST可以更新资源,那么它是如何不是幂等的?如果我使用PUT改变学生年龄并且这样做10倍,那么如果我做了一次,学生的年龄是相同的.
假设我们有可能有两个属性的实体 - "name"和"date".如果我们有一个具有现有`name`和`date`的实体,但是然后向它发出仅指定`name`的请求,那么**PUT**的正确行为将是删除实体的'date`,而**POST**可能只更新指定的属性,留下未指定的属性,就像它们在发出请求之前一样.这听起来是否正确/合理,或者是**PUT**的不当使用(我看到**PATCH**的引用,它似乎更合适,但还不存在)?
这已经死了,而且"接受"的答案在我看来(@brian)错过了这个关键的微妙之处.
是.事实上,AtomPub协议违背了这一点(或更准确地说,限制了它的PUT的语义含义):"PUT用于编辑已知资源.它不用于资源创建." 仅仅因为AtomPub协议这样说(顺便说一下)并不意味着所有RESTful协议都必须遵循它.(因为REST是通用的)
谢谢,这非常有帮助.为了进一步比喻,`POST`可以用来"赋值"(而不是`x ++`),但它更像是`obj.setX(5)` - `setX`方法*应该*导致x为5,但可能有副作用.
比较**PUT**和**POST**到mysql:**POST**就像一个`INSERT INTO`而没有提供自动增量列的ID,如果多次执行,你将创建多行.**PUT**就像使用`WHERE`语句中的主键的`UPDATE`,如果你多次执行,那么每行之后的行应该是相同的.一些供应商也可能允许你**PUT**来创建,这就像一个`INSERT INTO`为自动增量列提供一个值.

3> Nigel Thorne..:

POST到URL 服务器定义的URL上创建子资源.

PUT到URL 在客户端定义的 URL 处完整地创建/替换资源.

PATCH到URL 更新该客户端定义的URL的部分资源.

PUT和POST的相关规范是RFC2616§9.5ff.

POST会创建子资源,因此POST会/items创建一个位于资源下的/items资源.例如./items/1.两次发送相同的post数据包将创建两个资源.

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

因此:PUT只是CREATE的候选者,其中客户端在创建资源之前已经知道了url.例如./blogs/nigel/entry/when_to_use_post_vs_put因为标题用作资源键

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

RFC读起来像这样:

POST和PUT请求之间的根本区别体现在Request-URI的不同含义上.POST请求中的URI标识将处理所包含实体的资源.该资源可能是数据接受过程,某些其他协议的网关或接受注释的单独实体.与此相反,在URI的PUT请求识别附带请求的实体 - 用户代理知道URI打算和服务器不能尝试应用请求一些其他的资源.如果服务器希望将请求应用于不同的URI,

注意: PUT主要用于更新资源(通过全部替换它们),但最近有使用PATCH更新现有资源的动作,因为PUT指定它替换整个资源.RFC 5789.

更新2018:有一种情况可以避免PUT.请参阅"没有PUT的REST"

使用"REST without PUT"技术,其想法是消费者被迫发布新的"名词化"请求资源.如前所述,更改客户的邮件地址是对新"ChangeOfAddress"资源的POST,而不是具有不同邮件地址字段值的"Customer"资源的PUT.

取自REST API设计 - Thoughtworks的Prakash Subramaniam的资源建模

这会强制API避免多个客户端更新单个资源时的状态转换问题,并且更好地匹配事件源和CQRS.当工作异步完成时,POST转换并等待它应用似乎是合适的.


或者从围栏的另一侧:PUT如果客户端确定结果资源的地址,则在服务器执行POST时进行POST.
你是对的.将博客帖子放在与现有帖子相同的URL上会导致对现有帖子的更新(尽管您显然可以先使用GET进行检查).这表明为什么仅使用标题作为URL是个坏主意.然而,它可以在数据中存在自然键的任何地方工作......在我的经验中很少见.或者,如果您使用GUID
我试图理解,但是如果客户端确实知道资源还不存在,那么使用PUT创建一些东西才会有意义,对吧?根据博客示例,假设您在几年内创建了数百篇博客帖子,然后意外地选择了与两年前发布的帖子相同的标题.现在你已经离开并替换了那个不是故意的帖子.因此,使用PUT进行创建将需要客户端跟踪所采取的措施和不采取的措施,并且可能导致意外和意外的副作用,以及有两条完全不同的路线?
我认为应该编辑这个答案,以便更加清楚@DanMan以一种非常简单的方式指出的内容.我发现这里最有价值的是最后的注释,说明PUT应该仅用于替换整个资源.
PATCH至少在几年内不是一个现实的选择,但我同意这种意识形态.
@crush:为什么PATCH至少在几年内不是一个现实的选择?
HTTP说...当客户端"放入"网址时,它会请求该网址保存该数据.由服务器决定是否乐意这样做.如果你想要'删除'来阻止PUT工作......那就没关系,但你能再次在那个网址上找到任何东西吗?如果是这样,那么你可能应该让后续的PUT通过...在你的所有用户之后试图将内容放在该位置是有原因的.谁能说谁更正确?:)答案是......"你的域名".做什么模型你的域名.但是PUT的意思是"我想把它存放在这里".

4> 7hi4g0..:
摘要:

创建:

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

创建新的资源newResourceId作为标识符,/资源URI,或下收集.

PUT /resources/ HTTP/1.1 

POST

创建一个在/资源URI,或者在新的资源集合.通常,服务器返回标识符.

POST /resources HTTP/1.1

更新:

可以用下面的方式PUT进行:

使用existingResourceId作为标识符,在/ resources URI或集合下更新资源.

PUT /resources/ HTTP/1.1
说明:

当与REST和URI作为一般的处理,你有通用左边特定右侧.该仿制药通常被称为集合和更具体的项目可以被称为资源.请注意,资源可以包含集合.

例子:

< - generic - specific - >

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时,你总是引用一个集合,所以每当你说:

POST /users HTTP/1.1

您要将新用户发布到users 集合.

如果你继续尝试这样的事情:

POST /users/john HTTP/1.1

它会起作用,但从语义上讲,你要说的是要在users 集合下的john 集合中添加资源.

一旦您使用PUT,您就可以在集合中引用资源或单个项目.所以当你说:

PUT /users/john HTTP/1.1

您告诉服务器更新,或者创建它是否不存在,用户集合下的john 资源.

规格:

让我重点介绍一下规范的一些重要部分:

POST

POST方法用来请求原始服务器接受封闭在请求作为实体的新下属的请求URI中使用Request-Line标识的资源的

因此,在集合上创建新资源.

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

因此,基于资源的存在来创建或更新.

参考:

HTTP/1.1规范

维基百科 - REST

统一资源标识符(URI):通用语法和语义


这篇文章有助于我理解POST将"something"作为子项添加到给定集合(URI),而PUT明确定义给定URI位置的"something".
这是最好的答案,在这里,我认为:没有一个"POST可以更新资源"的废话.我喜欢你的陈述,"只能用PUT执行更新".
不,PUT不用于更新或创建.这是为了更换.请注意,您可以使用某些内容替换任何内容以获得创建效果.
@ 7hi4g0 PUT用于更新,完全替换,换句话说,它取代.你不用任何东西替换任何东西,或者用一些全新的东西替换.PUT不是为了进行微小的改变(除非你让客户做出微小的改变并提供整个新版本,即使是保持不变的版本).对于部分修改,PATCH是首选方法.

5> ThaDon..:

我想补充一下我的"务实"建议.当您知道可以检索要保存的对象的"id"时,请使用PUT.如果您需要返回数据库生成的ID以供将来查找或更新,则使用PUT将无法正常工作.

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

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

GET /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.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com


实际上,它应该是`POST/users`.(注意`/ users`是复数.)这具有创建新用户并使其成为`/ users`集合的子资源的效果.
@DavidRR公平,如何处理群体是另一场辩论.`GET/users`是有道理的,它会读取你想要的,但我很确定用`(用于表示新用户的有效载荷)GET /用户/ `或`POST/user`因为它正确地写着"得到我用户5'很奇怪,但'让我用户5'更自然.虽然:)我可能仍然会倒在多元化的一边:)

6> Alexander To..:

POST表示"创建新",如"以下是创建用户的输入,为我创建".

PUT表示"插入,替换,如果已经存在",如"这是用户5的数据".

您发布到example.com/users,因为您还不知道用户的URL,您希望服务器创建它.

由于您要替换/创建特定用户,因此请输入example.com/users/id .

使用相同数据发布两次意味着创建两个具有不同ID的相同用户.使用相同数据进行两次输入会创建第一个用户,并在第二次将其更新为相同状态(无更改).由于你在PUT之后无论你执行它多少次都会得到相同的状态,所以每次都被称为"同样有效" - 幂等.这对于自动重试请求很有用.当您按下浏览器上的后退按钮时,不再"您确定要重新发送"吗?

一般建议是在需要服务器控制资源的URL生成时使用POST.否则使用PUT.首选PUT over POST.


邋iness可能导致通常教导你只需要两个动词:GET和POST.GET获取,POST改变.甚至PUT和DELETE都是使用POST执行的.询问PUT在25年后真正意味着什么可能是一个迹象,我们一开始就错了.REST的受欢迎程度使人们重新回到基础,现在我们必须忘记过去的错误.POST过度使用,现在通常教不正确.最好的部分:"使用相同的数据发布两次意味着创建两个相同的[资源]".好点!

7> Tim Sullivan..:

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

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


这是一个公平的指导方针,但过于简单化了.正如其他答案所提到的,任何一种方法都可以用于创建和更新.
`POST/items`将新项添加到已定义的资源('item').正如答案所说,它并没有"创造一个群体".我不明白为什么这有12票.
我略微修改了同意答案.使用POST创建和PUT以完全更新资源.对于部分更新,我们可以使用PUT或PATCH.假设我们想要更新组的状态.我们可以使用PUT/groups/1/status,其状态是请求有效负载,或者PATCH/groups/1,其中包含有效负载中的操作的详细信息
还应该明确的是,"PUT/items/42"对于*创建*资源也是有效的,*但仅当客户端具有命名资源*的特权时才有效.(Rails是否允许客户端具有此命名权限?)

8> Premraj..:

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

在此输入图像描述

比喻:

PUT即取走并放置它的位置.

POST作为邮局发送邮件.

在此输入图像描述


@MobileMon不,REST方法不是CRUD.
总结一下:POST用于插入,PUT用于更新

9> Jörg W Mitta..:

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

如果您对如何在HTTP中实现REST有任何疑问,可以随时查看Atom发布协议(AtomPub)规范.AtomPub是一个用HTTP编写RESTful webservices的标准,由许多HTTP和REST杰出人员开发,其中一些来自REST的发明者和HTTP本身的发明者Roy Fielding.

实际上,您甚至可以直接使用AtomPub.虽然它来自博客社区,但它绝不仅限于博客:它是一种通用协议,用于通过HTTP与任意资源的任意(嵌套)集合进行REST交互.如果您可以将应用程序表示为嵌套的资源集合,那么您可以使用AtomPub而不用担心是使用PUT还是POST,返回哪些HTTP状态代码以及所有这些详细信息.

这就是AtomPub关于资源创建的说法(第9.2节):

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


允许PUT创建资源没有错.请注意,这意味着客户端提供了URL.
允许PUT创建资源有一些问题:客户端提供URL.这是服务器的工作!

10> Joshcodes..:

是否使用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-hypertext-driven

RESTful-URL的想法实际上违反了REST,因为服务器负责URL结构,应该可以自由决定如何使用它来避免耦合.如果这让您感到困惑,请阅读有关API设计中自我发现的重要性的信息.

使用POST创建资源需要考虑设计因素,因为POST不是幂等的.这意味着多次重复POST并不能保证每次都有相同的行为.这会让人们在不应该使用PUT时创建资源.他们知道这是错的(POST是为了CREATE),但他们仍然这样做,因为他们不知道如何解决这个问题.在以下情况中证明了这种担忧:

    客户端将新资源POST到服务器.

    服务器处理请求并发送响应.

    客户端从未收到响应.

    服务器不知道客户端没有收到响应.

    客户端没有资源的URL(因此PUT不是一个选项)并重复POST.

    POST不是幂等的,服务器......

第6步是人们常常对做什么感到困惑.但是,没有理由创建一个解决这个问题的方法.相反,HTTP可以按照RFC 2616中的规定使用,服务器回复:

10.4.10 409冲突

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

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

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

回复状态代码409 Conflict是正确的追索权,因为:

执行具有与系统中已有资源匹配的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应该用于创建.

有关此内容的更多信息,请阅读本文.



11> metamatt..:

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

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

这与其他建议相吻合,PUT最适用于已有名称的资源,POST适用于在现有资源下创建新对象(并让服务器为其命名).

我解释这个,以及对PUT的幂等性要求,意思是:

POST适用于在集合下创建新对象(并且创建不需要是幂等的)

PUT适用于更新现有对象(并且更新需要是幂等的)

POST也可以用于对现有对象的非幂等更新(特别是,在不指定整个对象的情况下更改对象的一部分 - 如果您考虑它,创建集合的新成员实际上是这种类型的特殊情况更新,从集合的角度来看)

当且仅当您允许客户端命名资源时,PUT也可用于创建.但是,由于REST客户端不应该对URL结构做出假设,因此这不符合预期的精神.


"POST也可以用于对现有对象的非幂等更新(特别是,在不指定整个对象的情况下更改对象的一部分"这就是PATCH的用途)

12> bharatj..:

简而言之:

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

POST是非幂等的,其中如果与执行单个时间相比多次执行操作,则资源状态可能变得不同.

与数据库查询类比

PUT你可以想到类似于"UPDATE STUDENT SET address ="abc"where id ="123";

POST您可以想到"INSERT INTO STUDENT(姓名,地址)VALUES("abc","xyzzz");

学生ID是自动生成的.

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

在POST的情况下,如果多次执行相同的查询,则在数据库中创建多个学生记录,并且每次执行"INSERT"查询时数据库状态都会更改.

注意: PUT需要一个需要更新的资源位置(已经是资源),而POST不需要.因此,直观地,POST用于创建新资源,而PUT用于更新已经存在的资源.

有些人可能会想到可以使用POST执行更新.没有硬性规则可以用于更新,也可以用于创建.这些都是惯例,直觉上我倾向于上面提到的推理并遵循它.


for*PUT*类似于**INSERT或UPDATE**查询

13> Homer6..:

POST就像在邮箱中发信或将电子邮件发送到电子邮件队列.PUT就像你把一个物体放在一个小房间或一个架子上的地方(它有一个已知的地址).

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

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

一般规则:如果您知道项目的ID或名称,请使用PUT.如果您希望接收方分配项目的ID或名称,请使用POST.

POST与PUT


id是URL的一部分,所以是的,如果您知道URL(包括id),请使用PUT.

14> Jordan..:

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

PUT仅仅是服务应该从现在开始用于呈现客户端识别的资源的表示的内容的陈述; POST是一个声明,说明服务从现在开始应该包含哪些内容(可能是重复的),但服务器应该如何识别该内容.

PUT x(如果x标识资源):"替换由x我的内容标识的资源的内容."

PUT x(如果x未标识资源):"创建包含我的内容的新资源,并使用x它来识别它."

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

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

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

PUT /something(如果/something已经存在的话):"拿走你所拥有的一切,/something并用我给你的东西取而代之."

PUT /something(如果/something还不存在的话):"把我给你的东西放进去吧/something."

POST /something:" /something只要你在完成后给我的URL ,就把我给你的东西放在任何你想要的地方."



15> ishandutta20..:

简答:

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

答案很长:

POST:

POST用于将数据发送到服务器.

资源的URL未知时很有用

放:

PUT用于将状态传输到服务器

知道资源的URL时很有用

更长的答案:

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

从REST架构的角度来看,没有一个重要.我们本可以没有PUT生活.但从客户开发人员的角度来看,这使他/她的生活变得更加简单.

在PUT之前,客户端无法直接知道服务器生成的URL或者是否已生成任何URL,或者是否已经更新了要发送到服务器的数据.PUT解除了所有这些头痛的开发人员.PUT是幂等的,PUT处理竞争条件,PUT允许客户端选择URL.


你的简短回答可能非常错误.HTTP代理可以自由重复HTTP PUT.因此,如果PUT实际上正在执行SQL INSERT,它可能会第二次失败,这意味着它将返回不同的结果,因此它不会是IDEMPOTENT(这是PUT和POST之间的区别)

16> germanlinux..:

Ruby on Rails 4.0将使用'PATCH'方法而不是PUT来进行部分更新.

RFC 5789谈到了PATCH(自1995年以来):

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

" Edge Rails:PATCH是新的主要HTTP更新方法 "解释说.



17> skillet-thie..:

有可能重述已经说过的内容,重要的是要记住,PUT意味着客户端在创建资源时控制URL最终会成为什么.因此,PUTPOST之间的选择部分将取决于您可以信任客户端提供多少正确的,规范化的URL,这些URL与您的URL方案一致.

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


我有点迟到了 - 但是有人在另一个网站上说类似的东西让我点击它.如果您正在创建资源并使用自动递增的ID作为"标识符"而不是用户指定的名称,则它应该是POST.
这不太对 - PUT仍然可以通过引用非规范名称来创建资源,只要在响应中,服务器返回一个*Location`标头**包含规范资源名称.

18> UniCoder..:

我以一个非常简单的方式来举例说明Facebook的时间表.

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

案例2:如果您的朋友第一次对您的帖子发表评论,那么也会在数据库中创建一个新条目,以便使用POST方法.

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

在单行线,使用POST来添加新条目的数据库和PUT更新数据库中的东西.


如果注释是具有用户id,创建日期,评论消息等属性的对象,并且在编辑时只有评论消息得到更新,PATCH应该在这里完成?

19> Hans Malherb..:

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

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

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

其他一些考虑:

POST使整个包含资源的缓存副本无效(更好的一致性)

POST请求时PUT响应不可缓存(需要内容位置和到期)

PME受Java ME,旧浏览器,防火墙等的支持较少



20> bbsimonbb..:

对这个主题不熟悉的读者会被关于你该做什么的无休止讨论以及相对缺乏经验教训所震惊.我认为,REST比SOAP更"优先"的事实是从经验中获得高水平的学习,但我们必须从那里取得进步吗?这是2016年.罗伊的论文是在2000年.我们开发了什么?它有趣吗?是否易于集成?支持?它会处理智能手机和移动连接的崛起吗?

根据ME,现实生活中的网络是不可靠的.请求超时.连接已重置.网络一次下降数小时或数天.火车进入隧道与移动用户搭乘.对于任何给定的请求(在所有这些讨论中偶尔都会承认),请求可以在途中落入水中,或者响应可以在返回途中落入水中.在这些情况下,直接针对实质性资源发出PUT,POST和DELETE请求一直让我觉得有点野蛮和天真.

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

或者您可以这样做:将您的不安全请求视为短暂的单用户资源(让我们称之为操作).客户端在实体资源上请求新的"操作",对资源进行空POST.POST将仅用于此目的.一旦安全地拥有新鲜动作的URI,客户端就将不安全的请求PUT发送到动作URI,而不是目标资源.解决操作并更新"真实"资源恰好是您的API的工作,并且在这里与不可靠的网络分离.

服务器执行业务,返回响应并将其存储在约定的操作URI中.如果出现任何问题,客户端会重复请求(自然行为!),如果服务器已经看到它,它会重复存储的响应并且不执行任何其他操作.

您将很快发现与promises的相似性:我们在执行任何操作之前创建并返回结果的占位符.也像承诺一样,动作可以成功或失败一次,但其结果可以重复获取.

最重要的是,我们为发送和接收应用程序提供了将唯一标识的操作与其各自环境中的唯一性相关联的机会.我们可以开始要求并执行!来自客户的负责任的行为:尽可能多地重复您的请求,但是在您拥有现有结果的确定结果之前不要生成新的操作.

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

连续删除请求可以查看和处理原始确认,而不会遇到404错误.如果事情花费的时间超过预期,我们可以临时回复,我们有一个地方,客户可以检查确定的结果.这种模式最好的部分是它的功夫(熊猫)属性.我们采取了一个弱点,即客户在不理解响应的情况下重复请求的倾向,并将其变为强度 :-)

在告诉我这不是RESTful之前,请考虑REST原则受到尊重的众多方式.客户端不构造URL.虽然语义上有一点变化,但API仍然是可发现的.适当使用HTTP谓词.如果你认为这是一个巨大的改变,我可以从经验告诉你,它不是.

如果您认为要存储大量数据,那就让我们来谈谈:典型的更新确认只是一个千字节的一小部分.HTTP目前为您提供一两分钟的明确回应.即使您只存储一周的行动,客户也有足够的机会赶上.如果您的产量非常高,您可能需要一个专用的符合酸性的键值存储或内存解决方案.



21> Rohit Dhiman..:

除了别人建议的差异之外,我想再添加一个.

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方法


为什么这没有被投票?如果是真的,这是一个关键的区别,不是吗?
我在为配置文件更新实现API时遇到了这个问题,其中包括用户配置文件pic上传.然后我用postman,Ajax,PHP curl和laravel 5.6作为后端进行了测试.

22> Burhan..:

似乎总是存在一些关于何时使用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(更新)操作.在某些情况下,可以将PUT用于创建,而在其他情况下,则需要POST.歧义在于HTTP PUT方法与HTTP POST方法的定义.

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

基于上面的幂等定义,我使用HTTP PUT方法与使用HTTP POST方法进行REST服务的方法是:在以下情况下使用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方法.


Update => HTTP POST:POST不用于更新

23> inf3rno..:

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

因此,您可以使用POST,但可能不需要PUT来创建资源.你不必支持两者.对我来说,POST就足够了.所以这是一个设计决定.

正如您的报价所提到的,您使用PUT创建没有分配给IRI的资源,并且您仍然想要创建资源.例如,PUT /users/123/password通常用新密码替换旧密码,但如果密码已经不存在(例如,由新注册的用户或通过恢复被禁用的用户),则可以使用它来创建密码.



24> Gerard ONeil..:

我打算用以下内容登陆:

PUT是指由URI标识的资源.在这种情况下,您正在更新它.它是三个动词中引用资源的一部分 - 删除并成为另外两个.

POST基本上是一种自由形式的消息,其含义被定义为"带外".如果消息可以解释为向目录添加资源,那就没问题,但基本上您需要了解要发送(发布)的消息以了解资源会发生什么.


因为PUT和GET和DELETE引用了资源,所以它们也是幂等的.

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

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


编辑:还有一件事 - PUT可以创建,但如果确实如此,则ID必须是自然ID - AKA是电子邮件地址.那样当你PUT两次时,第二次put是对第一次的更新.这使它成为幂等的.

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



25> Gregory Maga..:

语义应该是不同的,因为"PUT",如"GET"应该是幂等的 - 意思是,你可以多次执行相同的PUT请求,结果就像你只执行一次一样.

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

当您在特定URL上输入资源时,会发生的事情是它应该保存在该URL,或者沿着这些行保存.

当您对特定URL上的资源进行POST时,通常会向该URL发布相关信息.这意味着URL上的资源已经存在.

例如,当您想要创建新流时,可以将其设置为某个URL.但是,当您要将消息发布到现有流时,请POST到其URL.

至于修改流的属性,可以使用PUT或POST执行此操作.基本上,只有当操作是幂等的时才使用"PUT" - 否则使用POST.

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



26> tothemario..:

大多数时候,你会像这样使用它们:

POST资源到一个集合

PUT由collection /:id标识的资源

例如:

POST/items

PUT /items/1234

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

请注意,POST"创建"集合中的新元素,PUT"替换"给定URL处的元素,但使用PUT进行部分修改是一种非常常见的做法,即仅将其用于更新现有资源和仅修改正文中包含的字段(忽略其他字段).这在技术上是不正确的,如果你想要REST-purist,PUT应该替换整个资源,你应该使用PATCH进行部分更新.就我们所有API端点的行为清晰且一致而言,我个人并不在意.

请记住,REST是一组保持API简单的约定和指南.如果您最终只是为了检查"RESTfull"框而进行复杂的解决方案,那么您就是在挫败目的;)



27> Adam Griffit..:

这是一个简单的规则:

PUT到URL应该用于更新或创建可以位于该URL的资源.

应该使用POST到URL来更新或创建位于其他("从属")URL的资源,或者不能通过HTTP定位.


thecoshman - 你在这里滥用语义 - 如果它是相同的资源并且有一些差异,则替换可以是更新.如果使用replace来更改相同的资源,则replace仅对put有效.用新的和不同的资源替换是无效的(删除旧的并添加新的?),特别是如果'new'资源没有自然ID.POST,OTOH,可以创建,更新,替换和删除 - 使用post取决于是否有要解释的消息,例如"应用折扣",这可能会也可能不会改变资源,具体取决于逻辑.

28> Tom Stickel..:

虽然可能有一种不可知的方式来描述这些,但它似乎与网站答案中的各种陈述相冲突.

让我们在这里非常明确和直接.如果您是使用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开发人员.



29> Rajan..:

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

    选择

    插入

    更新

    删除

    合并(如果已经存在则更新,否则插入)

PUT用于合并和更新操作和POST用于插入.



30> java_geek..:

实际上,POST适用于创建资源.应在Location响应头中返回新创建的资源的URL.PUT应该用于完全更新资源.请理解这些是设计RESTful API时的最佳实践.这样的HTTP规范不限制使用PUT/POST,但有一些限制来创建/更新资源.请查看http://techoctave.com/c7/posts/71-twitter-rest-api-dissected,总结最佳实践.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有