前端前端·

PUT和POST的区别

发布时间:2024-08-28 18:43:06阅读量:45
普通文章
转载请注明来源

我们都知道,PUT和POST是HTTP的两个方法(Method),都可以用来向HTTP服务器提交数据。似乎用哪个都可以,但其实两者还是有本质的区别的。

网上关于两者区别的文章比较多,但有相当一部分绝对是误导人。所以这次特意查看了RFC7231,来澄清二者的区别。

首先直接摘出RFC7231中的的部分关键原文:

The fundamental difference between the POST and PUT methods is highlighted by the different intent for the enclosed representation. The target resource in a POST request is intended to handle the enclosed representation according to the resource’s own semantics, whereas the enclosed representation in a PUT request is defined as replacing the state of the target resource. Hence, the intent of PUT is idempotent and visible to intermediaries, even though the exact effect is only known by the origin server.

Proper interpretation of a PUT request presumes that the user agent knows which target resource is desired. A service that selects a proper URI on behalf of the client, after receiving a state-changing request, SHOULD be implemented using the POST method rather than PUT.

上面这两段描述的关键词就是“idempotent”(幂等),理解了这个词就理解了二者的本质区别。下面就围绕这个词从以下几个角度分析PUT和POST的区别。

1、使用PUT时,必须明确知道要操作的对象,例如:

PUT /customer/doc/1
{
"name": "John Doe"
}

上面的PUT请求明确是对编号为1的文档进行操作,这里编号为1的文档就是要操作的对象。如果该文档不存在,就创建该文档;如果文档已经存在,就直接整个替换文档内容。

2、 有人可能会质疑,上面的例子用POST也可以实现。没错,如果用将上例中的PUT接口改成POST接口,就是这样:

POST /customer/doc/
{
"name": "John Doe"
}

注意这里有一个重要的不同,这里POST请求并不知道要操作的对象,它只是向HTTP服务器提交一篇新文档,由HTTP服务器为该文档产生一个编号。这就是上面从RFC7231中摘出的第二段文字所描述的含义。

3、有人可能会继续质问:用POST也可以用来修改目标资源对象阿。说得还是没错。还是沿用上面的例子,稍作如下改动:

POST /customer/doc/1
{
"description": "I am a student"
}

这里的含义是给编号为1的文档增加一个属性“description”。注意这里有两个不同:

(1)这里编号为1的文档必须是已经存在的文档,否则必须使用PUT;

(2)这里是对目标对象的部分修改。只是增加了一个新属性“description”,之前的属性“name”不受影响。

4、最后简要总结一下,使用PUT时,必须明确知道要操作的对象,如果对象不存在,创建对象;如果对象存在,则全部替换目标对象。同样POST既可以创建对象,也可以修改对象。但用POST创建对象时,之前并不知道要操作的对象,由HTTP服务器为新创建的对象生成一个唯一的URI;使用POST修改已存在的对象时,一般只是修改目标对象的部分内容。

经过了以上4条的分析之后,对PUT和POST的区别应该很清楚了吧?再强调一遍,PUT是“idempotent”(幂等),意味着相同的PUT请求不管执行多少次,结果都是一样的。但POST则不是。就类似于"x=1"这条语句是幂等的,因为无论执行多少次,变量x的值都是1;但"x++"就不是幂等的,因为每执行一次,变量x的值都不一样。

当然,这里讲的都是规范,都是最佳实践(best practise)。如果你在实际开发中,不按这个来,没有人能管得了你;但是当你的REST API要开放给别人使用时,就会和大家所接受的“普世价值”违背,很可能就会发生各种问题。

如果还有疑问,欢迎留言交流讨论:)。

–END–

评论区

暂无评论,来发布第一条评论吧!

弦圈热门内容

Vue初学记录

网站开发,需要前端与后端的开发。前端指用户端、浏览器端,是用户能看得到的部分。后端指服务器端,是用户看不到的部分。前端开发,需要用到CSS3和HTML5以及JavaScript。后端开发能用的编程语言则很多了,主流的有python、java等,只要我们电脑能够使用的编程语言,服务端都能使用。目前流行前后端分离,后端只需要提供好接口就行了,前端直接使用后端的接口。前端三大框架:Vue、react、AngularVue是目前中国使用比较多的框架,因为创造这个框架的是中国人——前谷歌员工Even You。React框架则是Meta公司(原Facebook公司)创造的框架,Angular是谷歌建立的框架。从最近GitHub的数据上看,Vue是目前全世界下载量最多的框架,第二大的为React,第三为Angular。前端框架建立的目的,其实是为了方便开发,提高开发效率,降低开发难度。本质上,最后到浏览器那里,都是转换为CSS3、HTML5、JavaScript的语言。前端的开发,代码实现前,还需要设计UI界面,提高用户体验。因此,网站前后端开发分别对应三个职位——前端工程师、后端工程师、UI设计师 ...

如何使用Nuxt实现高亮代码块?

你也想像其他网站那样,可以高亮用户写的代码块吗?有两个Javascript库可以帮助你实现这一点,他们分别是Prism.js和highlight.js。在本教程中,我们将使用PrismJS来讲解如何实现代码块高亮。首先,使用npm安装PrismJS:npm install prismjs然后前往composables文件夹,并在里面新建文件prism.js,其内容如下:import Prism from 'prismjs' import 'prismjs/themes/prism-tomorrow.css' // You can choose other themes export default Prism就这样,PrismJS就安装并配置好了,你只需要每次需要高亮代码的时候调用highlightAll()函数就可以了。具体例子如下:<script lang="ts" setup> onMounted(()=>{ Prism.highlightAll() }) $fetch('https://www.example.com') .then((res)=& ...

Nginx服务器反向代理

1. nginx服务器Nginx与Apache为两大主流web服务器。而我的轻量级云服务器使用了nginx。因为nginx相比与apache更轻量,性能更好,不怎么占内存,适合中小型服务器。同时Nginx善于应对高并发场景,在多用户同时点击的情况下,服务器能负荷得住。又由于nginx的负载均衡,让多个用户打开网站没那么卡。nginx官网安装教程Installing NGINX Open Source | NGINX DocumentationDebian12安装nginx:sudo apt-get update sudo apt-get install nginx最后输入sudo nginx -v验证安装。2. Nginx服务器反向代理客户端对代理是无感知的,只需将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,再返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址

代数几何简介

1. Introduction代数几何是数学的核心领域,也是如今国际数学界的主流。代数几何与许多数学分支都存在广泛的联系,比如数论、微分几何、代数拓扑、复几何、表示论、同调代数、交换代数、偏微分方程等等,这些分支的发展同时也对代数几何起到促进作用。数学史上的许多重大的事件,比如,费马大定理、莫德尔猜想、韦伊猜想的证明都跟代数几何有关。同时,代数几何存在广泛的应用,比如密码学、弦理论、大数据、统计学习理论等等。代数几何之下有众多分支,比如复代数几何,热带几何,算术几何,远阿贝尔几何,$p$进霍奇理论(complex algebraic geometry, tropical geometry, arithmetic geometry, anabelian geometry, p-adic hodge theory),每个分支代表代数几何研究的一个大方向,而在每个大方向下,又有各种以不同的问题为导向的子方向。在这篇文章中,我们将会对代数几何,包括它的分支算术代数几何,做一个简短的介绍。2. An Introduction to Arithmetic Geometry算术几何是算术代数几何的简 ...

Python pip安装SSL证书错误

问题描述:正常使用pip install xxx安装会弹出错误,导致下载失败。必须增加trust host字段,才能下载成功:pip --trusted-host pypi.python.org install在cmd运行python -c "import ssl; print(ssl.get_default_verify_paths())"在默认路径里没有找到ca证书,而在Lib\site-packages\certifi文件夹中,却发现了cacert.pem文件。故而认为原因是ca证书丢失或者寻找ca证书路径出错,因此尝试修改pip的默认ca证书路径。pip.ini文件中有大量的pip配置信息,因此需要先找到该文件。在cmd通过pip -v config list发现,在多个路径中,都没有找到pip.ini文件。且了解到,pip会有一个默认的pip.conf文件(其实就是pip.ini),因此断定默认pip.ini配置文件丢失。解决办法:在python根目录中,新建pip.ini,在里面写上[global] index-url = https://mirrors.aliyun.co ...

Django上传图片时ImageField的max_length报错

我使用的版本是Django 4.2,有一个模型里定义了ImageField,以下面这个为例:class Example(models.Model) image = models.ImageField( blank=True, upload_to=my_image_path, )当我上传图片的时候,django返回了这样一个错误:Ensure this filename has at most 100 characters (it has 107)。在django文档中,我们可以发现:FileField 实例在数据库中被创建为 varchar 列,默认最大长度为 100 个字符。与其他字段一样,你可以使用 max_length 参数改变最大长度。并且要知道ImageField是FileField的子类:继承 FileField 的所有属性和方法,但也验证上传的对象是有效的图像。ImageField 实例在数据库中创建为 varchar 列,默认最大长度为 100 个字符。与其他字段一样,你可以使用 max_length 参数改变 ...