GET和POST
先下结论,GET 和 POST 方法没有实质区别,只是报文格式不同。 GET和POST的底层也是 TCP/IP。用的都是同一个传输层协议。 GET 、POST 能做的事情是一样的,只要我们给 GET 加上 Request body,给 POST加上 URL 参数,技术上是完全行得通的。他们之间的不同是由于浏览器或者服务端的限制造成的。
- GET 方法参数写法是固定的吗?
在约定中,我们的参数是写在 ?
后面,用 &
分割。我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行。
- POST 方法比 GET 方法安全?
按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。要想安全传输,就只有加密,也就是 HTTPS。
【note】:
一些疑惑:
http与https区别,get与post请求区别
- GET 方法的长度限制是怎么回事?
首先说明一点,HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。浏览器原因就不说了,服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL长度加限制。
- POST 方法会产生两个 TCP 数据包?
有些文章中提到,post 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。其实发送请求就是 POST 请求通常比 GET 请求大的原因,要是 POST 请求足够小的话也不用发两个数据包,属于浏览器行为。
- GET会被缓存,POST不会
关于缓存也是浏览器行为,绝大多数浏览器是不支持post缓存的
- POST不能收藏书签问题
收藏书签这个很类似浏览器上点返回按钮这种形式。POST请求用来提交一个表单的话,在浏览器中点返回的时候会重复提交,可能会产生错误,所以这种情况下点返回会弹出提示框提示用户。而 GET 的请求通常情况下不会有提交的操作,所以在点返回的时候不会产生 POST 的问题,也属于浏览器行为。
在其他文章中看到RFC顺便放一下。
Request For Comments(RFC)www.rfc-editor.org,是一系列以编号排定的文件。
这样说吧!RFC就是互联网的规范,我们通常所说的协议就是RFC的方式存在,http/1.1规范中RFC7231中涉及到了几个http的方法,其中定义了几个性质:
1.safe(安全性)
这里的安全和通常所理解的安全意义不同,就好比如果一个请求的语义本质上就是获取数据(只读),那么这个请求就是安全的。客户端向服务器发起的请求如果没有引起服务器端任何的状态变化,那么他就是安全的而post请求来提交数据必然会是服务器发生相应的变化。从这个维度来看,get请求相对服务器而言,是安全的,post则不安全的。
ldempotend(幂等性)
幂等通俗的来讲就是指同一个请求执行多次和仅执行一次的效果完全相等。这里来扯出幂等主要是为了处理同一个请求重复发送的情况,假如在请求响应之前失去连接,如果这个请求时幂等的,那么就可以放心的重发一次请求。所以可以得出get请求时幂等的,可以重复发送请求,post请求时不幂等的,重复请求可能会发生无法预知的后果。
cacheable(可缓存性)
顾名思义,就是一个请求是否可以被缓存,绝大多数部分,post都是不可缓存的(某些浏览器可能支持post缓存),但get是可以缓存的。
勉强理解一下大概就是:
get是请求获取指定资源,get方法时安全、幂等、可缓存的,get方法的报文主体没有任何语义。post是根据报文主体来对指定资源做出处理,post不安全,不幂等,不可缓存(大部分情况下)。
https://juejin.cn/post/6844903824738500615
GET和PUT区别
put:幂等性
PUT https://ihui.ink/images/2020/11/26/http-put HTTP/1.1
如果从 RESTful API 的角度来理解,PUT 方法是这么工作的:地址K
是由客户端决定的
- 把一个对象
V
绑定到地址K
上;今后请求地址K
时,就会返回对象V
。 - 如果地址
K
之前曾绑定过另一个对象,比如V0
,那么V0
会被V
替换。
PUT 方法应当支持幂等性。如果是同一个对象 V
,PUT 多次与 PUT 一次返回的结果应该是相同的。客户端可以利用 PUT 的幂等性安全地重试请求,保证客户端的请求至少被服务端处理一次。
【note】:
想想在kibnana里给elasticSearch中创建索引是用PUT请求的情况,没有索引时发送会创建个新的,有索引时会更新原来的。
post:非幂等性
POST https://ihui.ink/post-article HTTP/1.1
也就是说,地址 K
不是由客户端指定的,而是由服务端生成的。比如,服务端可能会根据日期和文章标题,为本文分配一个地址。
另外,与 PUT 方法不同,POST 方法是不支持幂等性的。同一个请求被处理两次,应当生成两份对象。换句话说,客户端应该只发送一次 POST 请求,而客户端的请求至多会被服务端处理一次。
现在问题来了,如果真的遇到了网络故障,客户端应该如何重试 POST 请求呢?解决方法其实很简单,我们可以在 POST 请求中隐藏一个唯一的 token,服务端在处理请求后把 token 存入数据库,如果这个 token 之前遇到过,服务端就知道这是重复的 POST 请求,可以不再处理了。
简要总结
使用PUT时,必须明确知道要操作的对象,如果对象不存在,创建对象;如果对象存在,则全部替换目标对象。同样POST既可以创建对象,也可以修改对象。但用POST创建对象时,之前并不知道要操作的对象,由HTTP服务器为新创建的对象生成一个唯一的URI;使用POST修改已存在的对象时,一般只是修改目标对象的部分内容。
经过了以上4条的分析之后,对PUT和POST的区别应该很清楚了吧?再强调一遍,PUT是“idempotent”(幂等),意味着相同的PUT请求不管执行多少次,结果都是一样的。但POST则不是。就类似于”x=1”这条语句是幂等的,因为无论执行多少次,变量x的值都是1;但”x++”就不是幂等的,因为每执行一次,变量x的值都不一样。
当然,这里讲的都是规范,都是最佳实践(best practise)。如果你在实际开发中,不按这个来,没有人能管得了你;但是当你的REST API要开放给别人使用时,就会和大家所接受的“普世价值”违背,很可能就会发生各种问题。