POST 和 PUT HTTP 请求有啥区别?
Posted
技术标签:
【中文标题】POST 和 PUT HTTP 请求有啥区别?【英文标题】:What's the difference between a POST and a PUT HTTP REQUEST?POST 和 PUT HTTP 请求有什么区别? 【发布时间】:2010-09-11 13:34:57 【问题描述】:它们似乎都是在body内部向服务器发送数据,那么它们有什么不同呢?
【问题讨论】:
这能回答你的问题吗? PUT vs. POST in REST 【参考方案1】:HTTP PUT:
PUT 将文件或资源放在特定的 URI 上,并且准确地放在该 URI 上。如果该 URI 中已有文件或资源,则 PUT 会替换该文件或资源。如果那里没有文件或资源,则 PUT 创建一个。 PUT 是idempotent,但矛盾的是,PUT 响应不可缓存。
HTTP 1.1 RFC location for PUT
HTTP POST:
POST 将数据发送到特定的 URI,并期望该 URI 上的资源来处理请求。此时的 Web 服务器可以确定如何处理指定资源上下文中的数据。 POST 方法不是idempotent,但是只要服务器设置了适当的 Cache-Control 和 Expires 标头,POST 响应是可缓存的。
官方 HTTP RFC 指定 POST 为:
现有资源的注释; 将消息发布到公告板、新闻组、邮件列表、 或类似的文章组; 提供数据块,例如提交结果 表单,数据处理过程; 通过追加操作扩展数据库。HTTP 1.1 RFC location for POST
POST 和 PUT 的区别:
RFC 本身解释了核心区别:
两者的根本区别 POST 和 PUT 请求反映在 的不同含义 请求-URI。 POST 请求中的 URI 标识将要使用的资源 处理封闭的实体。那 资源可能是接受数据的 进程,通往其他人的门户 协议或单独的实体 接受注释。相比之下, PUT 请求中的 URI 标识 请求中包含的实体—— 用户代理知道 URI 是什么 预期和服务器不得 尝试将请求应用于某些 其他资源。如果服务器愿意 该请求适用于 不同的URI,它必须发送一个301(永久移动)响应;用户代理可以然后使 它自己决定是否重定向请求。
另外,更简洁一点,RFC 7231 Section 4.3.4 PUT 状态(已添加重点),
4.3.4。放置
PUT 方法请求目标资源的状态
created
或replaced
具有由表示定义的状态 包含在请求消息负载中。
使用正确的方法,无关紧要:
REST ROA 与 SOAP 相比的一个好处是,在使用 HTTP REST ROA 时,它鼓励正确使用 HTTP 动词/方法。因此,例如,当您想在该确切位置创建资源时,您只会使用 PUT。而且您永远不会使用 GET 来创建或修改资源。
【讨论】:
我在规范中读到If the Request-URI does not point to an existing resource [...] the origin server *can* create the resource with that URI
。因此,如果 PUT 不存在则拒绝创建资源的实现是正确的,对吗?如果是这样,这在实践中会发生吗?或者实现通常也在 PUT 上创建?
在下一个 URL 处有一些额外的例外,这使得区别非常明显 - dzone.com/articles/put-vs-post
我不明白的是如何实现PUT的幂等性。通常,大多数 API 会在创建新资源时使用 ID 的自动生成。而在 PUT 中,如果资源不存在,则应该创建资源,但使用 URI 中指定的 ID,但是如果将 id 生成方法设置为自动,你怎么能这样做???
简而言之:POST 请求中的 URI 标识了将处理封闭实体的资源。 PUT 请求中的 URI 标识实体本身。
对 POST 方法的响应不可缓存,除非响应包含适当的 Cache-Control 或 Expires 标头字段【参考方案2】:
只有语义。
HTTP PUT
应该接受请求的主体,然后将其存储在 URI 标识的资源中。
HTTP POST
更通用。它应该在服务器上启动一个动作。该操作可能是将请求正文存储在 URI 标识的资源中,也可能是不同的 URI,也可能是不同的操作。
PUT 类似于文件上传。对 URI 的放置完全影响该 URI。对 URI 的 POST 可能会产生任何影响。
【讨论】:
暗示某项功能的可能并不实际【参考方案3】:举个REST风格的资源例子:
POST /books
带有一堆书籍信息可能会创建一本新书,并以标识该书的新 URL 进行响应:/books/5
。
PUT /books/5
必须要么创建一本 ID 为 5 的新书,要么将现有的书替换为 ID 5。
在非资源风格中,POST
可用于几乎任何有副作用的事情。另一个区别是 PUT
应该是幂等的 - 相同数据的多个 PUTs
到同一个 URL 应该没问题,而多个 POSTs
可能会创建多个对象或您的 POST
操作所做的任何事情。
【讨论】:
嗨,Bhollis,如果我使用 POST /books/5,会发生什么?它会抛出找不到资源吗? 我觉得幂等性是 PUT 和 POST 最明显和最重要的区别 嗨 ChanGan,这是 Wikipedia 对您的“POST /books/5”案例的解释:“不常用。将寻址的成员视为一个集合,并在它。” 这个答案给人的印象是 PUT 和 POST 可以在同一资源上定义,但是幂等性旁边的另一个区别是谁控制 ID 空间。在 PUT 中,用户通过创建具有特定 ID 的资源来控制 ID 空间。在 POST 中,服务器返回用户在后续调用(如 GET)中应引用的 ID。上面的内容很奇怪,因为它是两者的混合体。【参考方案4】:-
GET:从服务器检索数据。应该没有其他影响。
PUT:用请求负载替换目标资源。可用于更新或创建新资源。
PATCH:类似于 PUT,但仅用于更新现有资源中的某些字段。
POST:对有效负载执行特定于资源的处理。可用于不同的操作,包括创建新资源、上传文件或提交网络表单。
DELETE:从服务器中删除数据。
TRACE:提供一种测试服务器接收内容的方法。它只是返回发送的内容。
OPTIONS:允许客户端获取有关服务支持的请求方法的信息。相关的响应标头是 Allow with supported methods。在 CORS 中也用作预检请求,以通知服务器实际请求方法并询问自定义标头。
HEAD:仅返回响应标头。
CONNECT:当浏览器知道它与代理通信并且最终的 URI 以 https:// 开头时使用。 CONNECT 的目的是允许端到端加密的 TLS 会话,因此代理无法读取数据。
【讨论】:
最佳简短答案 使用 https 时是否在每次请求之前触发 CONNECT? 关于 PUT 和 POST 的信息在这个答案中是不正确的。 PUT 可用于创建新实体以及更新现有实体。 POST 更通用,可用于执行类似 PUT 中的操作,也可用于对传入实体执行任何其他操作(具有副作用),理想情况下,PUT 应该是幂等的,因为 POST 可能是也可能不是幂等【参考方案5】:PUT 是一种将内容“上传”到特定 URI 或覆盖该 URI 中已有内容的方法。
另一方面,POST 是一种提交与给定 URI 相关的数据的方式。
参考the HTTP RFC
【讨论】:
【参考方案6】:据我所知,PUT 主要用于更新记录。
POST - 创建文档或任何其他资源
PUT - 更新创建的文档或任何其他资源。
但要明确的是,PUT 通常会“替换”现有记录,如果存在则创建,如果不存在则创建..
【讨论】:
在这种情况下什么是记录?问题是关于 HTTP 请求的。 如果文档/资源已经存在,POST 会做什么?它会抛出错误,还是会正常运行? 这里不是您分享“据我所知”类型意见的地方。我们需要简短的书面答复。【参考方案7】:其他人已经发布了很好的答案,我只是想补充一点,对于大多数语言、框架和用例,您将处理POST
比PUT
更频繁。以至于PUT, DELETE,
等基本上都是琐事问题。
【讨论】:
【参考方案8】:请看:http://zacharyvoase.com/2009/07/03/http-post-put-diff/
我最近对网络开发人员的一种流行误解感到非常恼火,即 POST 用于创建资源,而 PUT 用于更新/更改资源。
如果您查看 RFC 2616(“超文本传输协议 – HTTP/1.1”)Section 9.6(“PUT”)的第 55 页,您将了解 PUT 的实际用途:
PUT 方法请求将封闭的实体存储在提供的 Request-URI 下。
还有一个方便的段落来解释 POST 和 PUT 之间的区别:
POST 和 PUT 请求的根本区别在于 Request-URI 的不同含义。 POST 请求中的 URI 标识将处理封闭实体的资源。该资源可能是一个数据接受进程,一个通往其他协议的网关,或者一个接受注释的单独实体。相反,PUT 请求中的 URI 标识了请求中包含的实体——用户代理知道 URI 的意图,服务器不得尝试将请求应用于其他资源。
它没有提到更新/创建之间的区别,因为那不是它的意义所在。这是关于这之间的区别:
obj.set_attribute(value) # A POST request.
还有这个:
obj.attribute = value # A PUT request.
所以,请停止传播这种流行的误解。阅读您的 RFC。
【讨论】:
这似乎毫无意义的粗鲁,而且以一种没用的方式迂腐。在您引用的 PUT 示例中,新实体在 RESTful api 中是“新”记录 - 并且可以在该位置访问。允许子成员像那样可变是否是一个好的设计选择是值得怀疑的(我认为这并不理想),但即使这样,你也正在使用一个亚种来攻击很多有用的信息。大多数情况下,通常所说的描述是对 RFC 内容的很好的陈述、总结,以及对通常和习惯做法的陈述。此外,礼貌也不会伤害您。 这不能得到足够的支持。 PUT 在 REST API 中没有位置。大多数时候,POST 表示正确的语义。 说得不好,但确实是对 RFC 的准确解释。看起来,Web 开发者世界充斥着大量错误信息。 @Beefster 没有“POST 指示”之类的东西。 Najeebul 在这里提出了一个很好的观点。你如何判断它表示什么?除了你只是使用它,因为从你学习它的第一天开始就一直这样使用它,但与其他人相比,你真的不知道为什么要使用它?【参考方案9】:Define operations in terms of HTTP methods
HTTP 协议定义了许多为请求分配语义含义的方法。大多数 RESTful Web API 使用的常见 HTTP 方法是:
GET 检索指定 URI 处的资源表示。响应消息的正文包含所请求资源的详细信息。
POST 在指定的 URI 处创建一个新资源。请求消息的正文提供了新资源的详细信息。请注意,POST 也可用于触发实际上不创建资源的操作。
PUT 创建或替换指定 URI 处的资源。请求消息的正文指定要创建或更新的资源。
PATCH 执行资源的部分更新。请求正文指定要应用于资源的更改集。
DELETE 删除指定 URI 处的资源。
特定请求的效果应取决于资源是集合还是单个项目。下表使用电子商务示例总结了大多数 RESTful 实现所采用的常见约定。并非所有这些请求都可以实现——这取决于具体的场景。
Resource | POST | GET | PUT | DELETE |
---|---|---|---|---|
/customers | Create a new customer | Retrieve all customers | Bulk update of customers | Remove all customers |
/customers/1 | Error | Retrieve the details for customer 1 | Update the details of customer 1 if it exists | Remove customer 1 |
/customers/1/orders | Create a new order for customer 1 | Retrieve all orders for customer 1 | Bulk update of orders for customer 1 | Remove all orders for customer 1 |
POST、PUT 和 PATCH 之间的区别可能令人困惑。
POST 请求创建一个资源。服务器为新资源分配一个 URI 并将该 URI 返回给客户端。在REST model
中,您经常将POST
请求应用于集合。新资源将添加到集合中。 POST
请求也可用于向现有资源提交数据以进行处理,而无需创建任何新资源。
PUT 请求创建资源或更新现有资源。客户端指定资源的 URI。请求正文包含资源的完整表示。如果具有此 URI 的资源已存在,则将其替换。否则,如果服务器支持这样做,则会创建一个新资源。 PUT
请求最常应用于作为单个项目的资源,例如特定客户,而不是集合。服务器可能支持更新但不支持通过PUT
创建。是否支持通过PUT
创建取决于客户端是否可以在资源存在之前有意义地将 URI 分配给资源。如果没有,则使用POST
创建资源并使用PUT or PATCH
进行更新。
PATCH 请求对现有资源执行部分更新。客户端指定资源的 URI。请求正文指定要应用于资源的一组更改。这比使用PUT
更有效,因为客户端只发送更改,而不是资源的整个表示。从技术上讲,PATCH
还可以创建一个新资源(通过指定一组对“空”资源的更新),如果服务器支持的话。
PUT
请求必须是幂等的。如果客户端多次提交相同的PUT
请求,结果应该始终相同(相同的资源将被修改为相同的值)。 POST and PATCH
请求不保证是幂等的。
【讨论】:
我认为你有 PUT 和 POST 倒退 没有。 PUT 用于将文字内容实际放置在 URL 中,它很少在 REST API 中占有一席之地。 POST 更抽象,涵盖了任何类型的添加内容,这些内容不具有“将这个确切的文件放在这个确切的 URL”的语义。 -1 因为除了 update 之外,PUT 还用于 create 一个 target 资源(标识的资源通过请求 URI),与不能创建目标资源的 POST 相反,因为它不是对资源状态(数据管理)的 CRUD 操作,而是 process 操作(参见 RFC 7231)。该进程可能会创建一个资源,但与目标资源不同,因此它确实是一个 CRUD 操作。 这是迄今为止对 Put 和 Post 最好、最准确的解释。它是唯一一个谈论客户端能够为结果资源提供有意义的 URI。【参考方案10】:POST 被认为是一种工厂类型的方法。您在其中包含数据以创建您想要的内容,而另一端的任何内容都知道如何处理它。 PUT 用于更新给定 URL 处的现有数据,或者在您知道 URI 将是什么但它不存在时创建新的东西(与 POST 相反,它将创建一些东西并返回一个 URL 到如有必要)。
【讨论】:
【参考方案11】:何时使用其中一个应该非常简单,但复杂的措辞是我们许多人混淆的根源。
何时使用:
当您想要修改已经是资源集合一部分的单一资源时,请使用PUT
。 PUT
替换整个资源。示例:PUT /resources/:resourceId
旁注:如果您想更新资源的一部分,请使用PATCH
。
如果要在资源集合下添加子资源,请使用
POST
。
示例:POST => /resources
一般:
通常,在实践中,始终使用PUT
进行 UPDATE 操作。
始终使用 POST
进行 CREATE 操作。
示例:
GET
/company/reports => 获取所有报告GET
/ company/reports/id => 获取“id”标识的报告信息POST
/company/reports => 创建新报告PUT
/company/reports/id => 更新由“id”标识的报告信息PATCH
/company/reports/id => 更新一个“id”标识的部分报告信息DELETE
/company/reports/id => 删除报告者“身份证”
【讨论】:
【参考方案12】:POST 和 PUT 的区别在于 PUT 是幂等的,也就是说,多次调用同一个 PUT 请求总是产生相同的结果(即没有副作用),而另一方面,重复调用一个 POST 请求多次创建同一个资源可能会产生(额外的)副作用。
GET
: 使用 GET 的请求只检索数据,即它请求指定资源的表示
POST
:它将数据发送到服务器以创建资源。请求正文的类型由 Content-Type 标头指示。它通常会导致服务器的状态变化或副作用
PUT
:创建新资源或用请求负载替换目标资源的表示
PATCH
: 用于对资源进行部分修改
DELETE
: 删除指定资源
TRACE
:它沿着到目标资源的路径执行消息环回测试,提供有用的调试机制
OPTIONS
: 用于描述目标资源的通信选项,客户端可以为 OPTIONS 方法指定一个 URL,或者星号 (*) 表示整个服务器。
HEAD
: 它要求一个与 GET 请求相同的响应,但没有响应正文
CONNECT
: 与目标资源标识的服务器建立隧道,可用于访问使用 SSL (HTTPS) 的网站
【讨论】:
【参考方案13】:用简单的话你可以说:
1.HTTP Get:用于获取一项或多项
2.HTTP Post:用于创建项目
3.HTTP Put:用于更新一个item
4.HTTP补丁:用于部分更新某项
5.HTTP Delete:用于删除一个项目
【讨论】:
【参考方案14】:值得一提的是,POST
会受到一些常见的跨站请求伪造 (CSRF) 攻击,而 PUT
则不会。
当受害者访问attackersite.com
时,PUT
无法使用以下 CSRF。
攻击的影响是受害者无意中删除了一个用户,因为它(受害者)在target.site.com
上以admin
登录,在访问attackersite.com
之前:
attackersite.com
上的恶意代码:
案例1:正常请求。保存的target.site.com
cookie 将由浏览器自动发送:(注意:仅在端点支持PUT
更安全,因为它不是受支持的<form>
属性值)
<!--deletes user with id 5-->
<form id="myform" method="post" action="http://target.site.com/deleteUser" >
<input type="hidden" name="userId" value="5">
</form>
<script>document.createElement('form').submit.call(document.getElementById('myform'));</script>
案例 2: XHR 请求。保存的target.site.com
cookie 将由浏览器自动发送:(注意:仅在端点支持PUT
更安全,因为尝试发送PUT
会触发预检请求,其响应会阻止浏览器请求deleteUser
页面)
//deletes user with id 5
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://target.site.com/deleteUser");
xhr.withCredentials=true;
xhr.send(["userId=5"]);
MDN Ref : [..]不像“简单请求”(上面讨论过),--[[ 意思是:POST/GET/HEAD ]]--,对于“预检”请求,浏览器首先使用发送一个 HTTP 请求OPTIONS 方法[..]
cors in action : [..]某些类型的请求,例如 DELETE 或 PUT,在发出实际请求之前需要进一步请求服务器的许可[..]所谓的预检请求[ ..]
【讨论】:
【参考方案15】:REST-ful 用法
POST
用于创建新资源,然后返回资源URI
EX
REQUEST : POST ..../books
"book":"booName",
"author":"authorName"
此调用可能会创建一本新书并返回该书URI
Response ...THE-NEW-RESOURCE-URI/books/5
PUT
用于替换资源,如果该资源存在则简单地更新它,但如果该资源不存在则创建它,
REQUEST : PUT ..../books/5
"book":"booName",
"author":"authorName"
使用PUT
,我们知道资源标识符,但POST
将返回新的资源标识符
非 REST-ful 用法
POST
用于在服务器端发起一个动作,这个动作可能会也可能不会创建资源,但是这个动作总会有副作用,它会改变服务器上的某些东西
PUT
用于在特定 URL 处放置或替换文字内容
REST-ful 和非 REST-ful 风格的另一个区别
POST
是非幂等操作:同一个请求多次执行会导致一些变化。
PUT
是幂等操作:同一个请求多次执行不会有副作用。
【讨论】:
【参考方案16】:其实除了他们的标题没有什么不同。 GET 和其他方法之间实际上有一个基本的区别。使用“GET”-Request 方法,您在 url-address-line 中发送数据,首先用问号分隔,然后用 & 号分隔。
但是使用“POST”-request 方法,您不能通过 url 传递数据,但您必须在所谓的请求“body”中将数据作为对象传递。在服务器端,您必须读出接收到的内容的主体,以获取发送的数据。 但是另一方面,当您发送“GET”请求时,不可能在正文中发送内容。
声称“GET”仅用于获取数据而“POST”用于发布数据的说法是绝对错误的。根据“GET”请求或“POST”请求发送的数据,没有人可以阻止您创建新内容、删除现有内容、编辑现有内容或在后端执行任何操作。没有人可以阻止您以某种方式编写后端代码,即通过“POST”请求,客户端要求一些数据。
对于一个请求,无论你使用哪种方法,你调用一个URL并发送或不发送一些数据来指定,你想将哪些信息传递给服务器来处理你的请求,然后客户端得到来自服务器的回答。数据可以包含您想要发送的任何内容,后端可以对数据执行任何操作,响应可以包含您想要放入的任何信息。
只有这两种基本方法。获取和发布。但正是它们的结构使它们与众不同,而不是您在后端编写的代码。在后端,您可以使用接收到的数据编写任何您想要的代码。但是对于“POST”请求,您必须在正文中而不是在 url-addressline 中发送/检索数据,对于“GET”请求,您必须在 url-addressline 中发送/检索数据而不是在身体。就这样。
所有其他方法,如“PUT”、“DELETE”等,它们的结构与“POST”相同。
主要使用POST方法,如果你想隐藏一些内容,因为无论你在url-addressline中写入什么,都会保存在缓存中,GET-Method与写入url-addressline相同与数据。因此,如果您想发送敏感数据,不一定是用户名和密码,而是例如一些您不希望在 url-address-line 中显示的 id 或哈希,那么您应该使用 POST 方法.
此外,URL-Addressline 的长度限制为 1024 个符号,而“POST”方法不受限制。因此,如果您有大量数据,您可能无法使用 GET-Request 发送它,但您需要使用 POST-Request。所以这也是 POST 请求的另一个优点。
但是,当您没有复杂的文本要发送时,处理 GET 请求要容易得多。 否则,这是 POST 方法的另一个优点,即使用 GET 方法您需要对文本进行 url 编码,以便能够在文本甚至空格中发送一些符号。但是使用 POST 方法,您没有任何限制,您的内容不需要以任何方式更改或操作。
【讨论】:
【参考方案17】:总结
使用PUT
来创建或替换目标 资源的状态,该状态由请求中包含的表示定义的状态。 标准化的预期效果是幂等的,因此它通知中介他们可以在通信失败的情况下重复请求。
在其他情况下使用POST
(包括创建或替换目标资源以外的资源的状态)。其预期效果未标准化,因此中介不能依赖任何通用属性。
参考文献
POST
和 PUT
请求方法之间语义差异的最新权威描述见 RFC 7231(Roy Fielding,Julian Reschke,2014):
POST
和PUT
方法之间的根本区别在于封闭表示的不同意图。POST
请求中的目标资源旨在根据资源自身的语义处理封闭表示,而PUT
请求中的封闭表示被定义为替换目标资源的状态。因此,PUT
的意图是幂等的并且对中介可见,即使确切的效果只有源服务器知道。
换句话说,PUT
的预期效果是标准化(使用包含在request) 对所有目标资源都是通用的,而POST
的预期效果是未标准化,因此特定于每个目标资源。因此POST
可以用于任何事情,包括实现PUT
的预期效果和其他请求方法(GET
、HEAD
、DELETE
、CONNECT
、OPTIONS
和TRACE
) .
但建议在适用时始终使用更专业的请求方法而不是POST
,因为它为中介提供更多信息以实现信息检索的自动化(因为GET
、HEAD
、OPTIONS
和@987654346 @被定义为安全),处理通信失败(因为GET
、HEAD
、PUT
、DELETE
、OPTIONS
和TRACE
被定义为幂等),并优化缓存性能(因为GET
和HEAD
被定义为可缓存),如It Is Okay to Use POST(Roy Fielding,2009)中所述:
POST
仅在使用其他方法非常适合的情况下才会成为问题:例如,检索应该是某些资源 (GET
) 表示的信息,完全替换表示(PUT
),或任何其他标准化方法,这些方法可以告诉中介比“这可能会改变某些事情”更有价值的事情。其他方法对中介更有价值,因为它们说明了如何自动处理故障以及中间缓存如何优化它们的行为。POST
没有这些特征,但这并不意味着我们可以没有它。POST
在 HTTP 中有许多有用的用途,包括“此操作不值得标准化”的一般用途。
【讨论】:
【参考方案18】:PUT 和 POST 都是 Rest 方法。
PUT - 如果我们使用 PUT 两次使用相同的参数发出相同的请求,第二次请求将不会有任何效果。这就是为什么 PUT 通常用于 Update 场景的原因,使用相同的参数多次调用 Update 不会做比初始调用更多的事情,因此 PUT 是幂等的。
POST 不是幂等的,例如 Create 将在目标中创建两个单独的条目,因此它不是幂等的,因此 CREATE 在 POST 中被广泛使用。
每次使用相同参数的 POST 进行相同的调用会导致两种不同的事情发生,因此为什么 POST 通常用于 Create 场景
【讨论】:
【参考方案19】:Post 和 Put 主要用于发布数据和其他更新数据。但是你可以只对 post 请求做同样的事情。
【讨论】:
【参考方案20】:POST 和 PUT 的区别在于 PUT 请求是幂等的。也就是说,多次调用相同的 PUT 请求将始终产生相同的结果。相反,重复调用 POST 请求会产生多次创建相同资源的副作用。
【讨论】:
以上是关于POST 和 PUT HTTP 请求有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章