从设计意图上看
Get 方法的含义是请求从服务器获取资源,这个资源可以是静态的文本、页面、图片视频等。而 POST 方法相反,它向 URI 指定的资源提交数据,数据就放在报文的 body 里。
比如,在文章底部,敲入了留言后点击「提交」,浏览器就会执行一次 POST 请求,把你的留言文字放进了报文 body 里,然后拼接好 POST 请求头,通过 TCP 协议发送给服务器。
从使用上看
- GET 提交的数据会包含在 URL 中,并且请求参数会被完整的保留在浏览器的记录里,由于参数直接暴露在 URL 中,可能会存在安全问题,因此往往用于获取资源信息。而 POST 参数放在请求主体中,并且参数不会被保留,相比 GET 方法,POST 方法更安全,主要用于修改服务器上的资源。
- GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
- GET 请求只支持 URL 编码,POST 请求支持多种编码格式。
- GET 提交的数据大小有限制(这里所说的限制是针对浏览器而言的),而 POST 方法提交的数据没限制。
- GET 只支持 ASCII 字符格式的参数,而 POST 方法没有限制。
从本质上看
GET 和 POST 是 HTTP 协议中的两种发送请求的方法。
由于 HTTP 的底层是 TCP/IP ,所以 GET 和 POST 的底层也是 TCP/IP ,也就是说,GET / POST 都是 TCP 链接。GET 和 POST 能做的事情是一样的。如果你要给 GET 加上 request body ,或是给 POST 带上 URL 参数,技术上是完全可行的。
那么,上面从“使用上看”的那些参数大小的限制和其他规定又是从哪来的呢?答案是浏览器。
虽然理论上,你可以在 URL 中无限加参数,但浏览器会限制长度来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制 URL 长度在 2K 个字节,而(大多数)服务器最多处理 64K 大小的 URL 。超过的部分,恕不处理。如果你用 GET 服务,在 request body 偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会读出数据,有些服务器直接忽略,所以,虽然 GET 可以带request body,也不能保证一定能被接收到。
GET 和 POST 本质上就是 TCP 链接,并无差别。但是由于 HTTP 的规定和 浏览器/服务器 的限制,导致他们在应用过程中体现出一些不同。
细节补充
- GET 方法产生一个 TCP 数据包,POST 方法有时会产生两个(并不是所有的浏览器中都产生两个)。
对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务端响应 200,请求成功。
对于 POST 方式的请求,浏览器会先发送 http header 给服务端,告诉服务端等一下会有数据过来,服务端响应 100 continue ,告诉浏览器我已经准备接收数据,浏览器再 POST 发送一个 data 给服务端,服务端响应 200 ,请求成功。
但是上面所说的 POST 会比 GET 多一个 TCP 包其实不太严谨。多发的那个 expect 100 continue header 报文,是由客户端对 HTTP 的 POST 和 GET 的请求策略决定的,目的是为了避免浪费资源,如带宽,数据传输消耗的时间等等。所以客户端会在发送 header 的时候添加 expect 100 去探探路,如果失败了就不用继续发送 data ,从而减少了资源的浪费。所以是否在发送一个包取决了客户端的实现策略,和 GET / POST 并没什么关系。有的客户端比如 fireFox 就只发送一个包。
关于产生「数据包」的问题,更多是的客户端的所做出的优化行为,而不是 GET 方法和 POST 方法本质上的区别。
REF
https://zhuanlan.zhihu.com/p/22536382
https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4