根据HTTP/1.1规范:
该
POST
方法用来请求原始服务器接受被附在请求由标识的资源的新下属实体Request-URI
的Request-Line
换句话说,POST
用于创建.
该
PUT
方法请求将所包含的实体存储在提供的实体下Request-URI
.如果Request-URI
引用已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本.如果Request-URI
未指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源.
也就是说,PUT
用于创建或更新.
那么,应该使用哪一个来创建资源?或者需要支持两者?
总体:
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/
你可以在网上找到断言
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
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执行:
放
创建的新的资源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方法用来请求原始服务器接受封闭在请求作为实体的新下属的请求URI中使用Request-Line标识的资源的
因此,在集合上创建新资源.
该PUT方法要求将封闭实体存储所提供的请求URI下.如果Request-URI引用已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本.如果Request-URI 未指向现有资源,并且该URI 能够被请求用户代理定义为新资源,则源服务器可以使用该URI 创建资源.
因此,基于资源的存在来创建或更新.
参考:
HTTP/1.1规范
维基百科 - REST
统一资源标识符(URI):通用语法和语义
我想补充一下我的"务实"建议.当您知道可以检索要保存的对象的"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表示"创建新",如"以下是创建用户的输入,为我创建".
PUT表示"插入,替换,如果已经存在",如"这是用户5的数据".
您发布到example.com/users,因为您还不知道用户的URL,您希望服务器创建它.
由于您要替换/创建特定用户,因此请输入example.com/users/id .
使用相同数据发布两次意味着创建两个具有不同ID的相同用户.使用相同数据进行两次输入会创建第一个用户,并在第二次将其更新为相同状态(无更改).由于你在PUT之后无论你执行它多少次都会得到相同的状态,所以每次都被称为"同样有效" - 幂等.这对于自动重试请求很有用.当您按下浏览器上的后退按钮时,不再"您确定要重新发送"吗?
一般建议是在需要服务器控制资源的URL生成时使用POST.否则使用PUT.首选PUT over POST.
使用POST创建,PUT更新.无论如何,Ruby on Rails就是这样做的.
PUT /items/1 #=> update POST /items #=> create
两者都用于客户端到服务器之间的数据传输,但它们之间存在细微差别,它们是:
比喻:
PUT即取走并放置它的位置.
POST作为邮局发送邮件.
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或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应该用于创建.
有关此内容的更多信息,请阅读本文.
我喜欢这个建议,来自RFC 2616对PUT的定义:
POST和PUT请求之间的根本区别体现在Request-URI的不同含义上.POST请求中的URI标识将处理所包含实体的资源.该资源可能是数据接受过程,某些其他协议的网关或接受注释的单独实体.相反,PUT请求中的URI标识请求附带的实体 - 用户代理知道URI的用途,并且服务器不得尝试将请求应用于其他资源.
这与其他建议相吻合,PUT最适用于已有名称的资源,POST适用于在现有资源下创建新对象(并让服务器为其命名).
我解释这个,以及对PUT的幂等性要求,意思是:
POST适用于在集合下创建新对象(并且创建不需要是幂等的)
PUT适用于更新现有对象(并且更新需要是幂等的)
POST也可以用于对现有对象的非幂等更新(特别是,在不指定整个对象的情况下更改对象的一部分 - 如果您考虑它,创建集合的新成员实际上是这种类型的特殊情况更新,从集合的角度来看)
当且仅当您允许客户端命名资源时,PUT也可用于创建.但是,由于REST客户端不应该对URL结构做出假设,因此这不符合预期的精神.
简而言之:
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执行更新.没有硬性规则可以用于更新,也可以用于创建.这些都是惯例,直觉上我倾向于上面提到的推理并遵循它.
POST就像在邮箱中发信或将电子邮件发送到电子邮件队列.PUT就像你把一个物体放在一个小房间或一个架子上的地方(它有一个已知的地址).
使用POST,您将发布到QUEUE或COLLECTION的地址.使用PUT,您可以使用ITEM的地址.
PUT是幂等的.您可以发送请求100次,这无关紧要.POST不是幂等的.如果您发送请求100次,您将在邮政信箱中收到100封电子邮件或100封信件.
一般规则:如果您知道项目的ID或名称,请使用PUT.如果您希望接收方分配项目的ID或名称,请使用POST.
新的答案(现在我更了解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 ,就把我给你的东西放在任何你想要的地方."
简答:
简单的经验法则:使用POST创建,使用PUT进行更新.
答案很长:
POST:
POST用于将数据发送到服务器.
资源的URL未知时很有用
放:
PUT用于将状态传输到服务器
知道资源的URL时很有用
更长的答案:
为了理解它,我们需要质疑为什么PUT是必需的,PUT试图解决的问题是POST不能解决的问题.
从REST架构的角度来看,没有一个重要.我们本可以没有PUT生活.但从客户开发人员的角度来看,这使他/她的生活变得更加简单.
在PUT之前,客户端无法直接知道服务器生成的URL或者是否已生成任何URL,或者是否已经更新了要发送到服务器的数据.PUT解除了所有这些头痛的开发人员.PUT是幂等的,PUT处理竞争条件,PUT允许客户端选择URL.
Ruby on Rails 4.0将使用'PATCH'方法而不是PUT来进行部分更新.
RFC 5789谈到了PATCH(自1995年以来):
需要一种新方法来提高互操作性并防止错误.PUT方法已经定义为使用完整的新主体覆盖资源,并且不能重用以进行部分更改.否则,代理和缓存,甚至客户端和服务器可能会对操作结果感到困惑.已经使用了POST但没有广泛的互操作性(例如,没有标准的方法来发现补丁格式支持).早期的HTTP规范中提到了PATCH,但没有完全定义.
" Edge Rails:PATCH是新的主要HTTP更新方法 "解释说.
有可能重述已经说过的内容,重要的是要记住,PUT意味着客户端在创建资源时控制URL最终会成为什么.因此,PUT和POST之间的选择部分将取决于您可以信任客户端提供多少正确的,规范化的URL,这些URL与您的URL方案一致.
当您无法完全信任客户端做正确的事情时,使用POST创建新项目然后在响应中将URL发送回客户端会更合适.
我以一个非常简单的方式来举例说明Facebook的时间表.
案例1:当您在时间轴上发布内容时,这是一个全新的条目.所以在这种情况下,他们使用POST方法,因为POST方法是非幂等的.
案例2:如果您的朋友第一次对您的帖子发表评论,那么也会在数据库中创建一个新条目,以便使用POST方法.
案例3:如果您的朋友编辑了他的评论,在这种情况下,他们有一个评论ID,因此他们将更新现有评论,而不是在数据库中创建新条目.因此,对于这种类型的操作,使用PUT方法,因为它是幂等的.*
在单行线,使用POST来添加新条目的数据库和PUT来更新数据库中的东西.
最重要的考虑因素是可靠性.如果POST消息丢失,则系统的状态未定义.自动恢复是不可能的.对于PUT消息,只有在第一次成功重试之前,状态才是未定义的.
例如,使用POST创建信用卡交易可能不是一个好主意.
如果您的资源上碰巧有自动生成的URI,您仍然可以通过将生成的URI(指向空资源)传递给客户端来使用PUT.
其他一些考虑:
POST使整个包含资源的缓存副本无效(更好的一致性)
POST请求时PUT响应不可缓存(需要内容位置和到期)
PME受Java ME,旧浏览器,防火墙等的支持较少
对这个主题不熟悉的读者会被关于你应该做什么的无休止讨论以及相对缺乏经验教训所震惊.我认为,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目前为您提供一两分钟的明确回应.即使您只存储一周的行动,客户也有足够的机会赶上.如果您的产量非常高,您可能需要一个专用的符合酸性的键值存储或内存解决方案.
除了别人建议的差异之外,我想再添加一个.
在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方法
似乎总是存在一些关于何时使用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方法.
源服务器可以使用该URI创建资源
因此,您可以使用POST,但可能不需要PUT来创建资源.你不必支持两者.对我来说,POST就足够了.所以这是一个设计决定.
正如您的报价所提到的,您使用PUT创建没有分配给IRI的资源,并且您仍然想要创建资源.例如,PUT /users/123/password
通常用新密码替换旧密码,但如果密码已经不存在(例如,由新注册的用户或通过恢复被禁用的用户),则可以使用它来创建密码.
我打算用以下内容登陆:
PUT是指由URI标识的资源.在这种情况下,您正在更新它.它是三个动词中引用资源的一部分 - 删除并成为另外两个.
POST基本上是一种自由形式的消息,其含义被定义为"带外".如果消息可以解释为向目录添加资源,那就没问题,但基本上您需要了解要发送(发布)的消息以了解资源会发生什么.
因为PUT和GET和DELETE引用了资源,所以它们也是幂等的.
POST可以执行其他三个功能,但随后请求的语义将丢失在缓存和代理等中介上.这也适用于在资源上提供安全性,因为帖子的URI不一定表示它正在应用的资源(尽管如此).
PUT不需要是创造; 如果尚未创建资源,则服务可能会出错,但否则会更新它.反之亦然 - 它可能会创建资源,但不允许更新.PUT唯一需要的是它指向一个特定的资源,它的有效载荷是该资源的表示.成功的PUT意味着(禁止干扰)GET将检索相同的资源.
编辑:还有一件事 - PUT可以创建,但如果确实如此,则ID必须是自然ID - AKA是电子邮件地址.那样当你PUT两次时,第二次put是对第一次的更新.这使它成为幂等的.
如果生成了ID(例如,新的员工ID),则具有相同URL的第二个PUT将创建违反幂等规则的新记录.在这种情况下,动词将是POST,而消息(不是资源)将使用此消息中定义的值创建资源.
语义应该是不同的,因为"PUT",如"GET"应该是幂等的 - 意思是,你可以多次执行相同的PUT请求,结果就像你只执行一次一样.
我将描述我认为最广泛使用且最有用的约定:
当您在特定URL上输入资源时,会发生的事情是它应该保存在该URL,或者沿着这些行保存.
当您对特定URL上的资源进行POST时,通常会向该URL发布相关信息.这意味着URL上的资源已经存在.
例如,当您想要创建新流时,可以将其设置为某个URL.但是,当您要将消息发布到现有流时,请POST到其URL.
至于修改流的属性,可以使用PUT或POST执行此操作.基本上,只有当操作是幂等的时才使用"PUT" - 否则使用POST.
但请注意,并非所有现代浏览器都支持GET或POST以外的HTTP谓词.
大多数时候,你会像这样使用它们:
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"框而进行复杂的解决方案,那么您就是在挫败目的;)
这是一个简单的规则:
PUT到URL应该用于更新或创建可以位于该URL的资源.
应该使用POST到URL来更新或创建位于其他("从属")URL的资源,或者不能通过HTTP定位.
虽然可能有一种不可知的方式来描述这些,但它似乎与网站答案中的各种陈述相冲突.
让我们在这里非常明确和直接.如果您是使用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开发人员.
如果您熟悉数据库操作,则有
选择
插入
更新
删除
合并(如果已经存在则更新,否则插入)
我PUT
用于合并和更新操作和POST
用于插入.
实际上,POST适用于创建资源.应在Location响应头中返回新创建的资源的URL.PUT应该用于完全更新资源.请理解这些是设计RESTful API时的最佳实践.这样的HTTP规范不限制使用PUT/POST,但有一些限制来创建/更新资源.请查看http://techoctave.com/c7/posts/71-twitter-rest-api-dissected,总结最佳实践.