推荐文章中,再次理解了GET与POST。

GET与POST是HTTP请求的两种方式,每次谈到,不免都是想说这两者的区别嘛,之前自己也只是模糊的知道POST方法好一点,为什么,自己也只能回答一句,安全一点嘛,觉得说得太少了,于是去搜索了一下,以下是w3schools给出的答案:

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET产生的URL地址可以被Bookmark,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。

说得真是有道理,没错啊,这就是区别啊,但是这样的答案大家背一背什么的就都会说了,但是这就完了吗?以上的自己都能理解,但是我觉得都只是现象,并不是原因啊!于是继续懵逼,直到看到下面的解释,自己好像慢慢开始理解了。

原文链接99%的人都理解错了GET与POST

既然说GET与POST是HTTP请求的两种方式,那什么是HTTP?

学过一点计算机网络的我有点印象,但是也不记得官方咋说的了,于是借鉴一下别人的话:

HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。

那既然HTTP的底层是TCP/IP,GET与POST自然也是基于TCP/IP咯,那GET与POST就是TCP/IP的两种链接方式了,那它们的区别到底在哪里呢?

借助原文的比喻:

在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

既然只是对传输数据的方式有要求,那关于参数的大小要求又从哪里来的?

这就是“运输公司”——浏览器和服务器不同导致的,业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到。

现在,我知道了,GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。这个时候我觉得标准答案的现象我都可以解释了。

紧接着,我又看到了一个令我目瞪口呆的区别:

简单的说:
GET产生一个TCP数据包;POST产生两个TCP数据包。

这是什么情况,我难道睡觉的时候老师讲重点了!!!???反正就是现在才知道这么重要的知识点。

好吧,了解之后明白了,GET在请求的时候会一次性将header和data发出去,然后服务器响应200(返回数据);而POST会先发header,等到服务器响应100(continue)的时候再发送data,然后服务器返回200(返回数据)。

POST两次发送骤导致时间上消耗要多一点,那GET看起来就更有效了,于是Yahoo团队推荐将所有的POST请求用GET请求替换,以此来优化网页性能,无可厚非这可以达到一定效果,但很明显也是一个坑啊!

为什么?

  • 存在即合理啊!(GET与POST都有自己的语义,不能随便混用。)

  • 网速够快这点时间可以忽略(据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。),而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

  • 并不是所有“运输公司”(浏览器)都会在POST中发送两次包,Firefox就只发送一次。