一、前言
今天研究了一下HTTP
协议中,GET
方法与POST
方法的区别。一研究发现,GET
和POST
完全不似我学习Web
开发时了解的那般,它们之间的关系完全颠覆了我之前的理解。这篇博客我就来从两个层面谈一谈GET
与POST
的区别——浏览器层面以及报文层面。
二、正文
2.1 浏览器层面的区别
GET
和POST
方法在浏览器层面的区别大部分人或多或少都知道一些,它主要包含以下几个方面:
通过以上区别,我们归纳为以下两点:
- GET:它用来向服务器请求资源,所以没有副作用,而且它是幂等的,可以被缓存;
- POST:用来请求服务器修改数据,所以有副作用,它是非幂等的,不能被缓存;
HTTP
中的幂等:每次请求会产生同样的副作用。
GET
是幂等的,因为它只是请求资源,不会对服务器产生影响,也就是没有副作用,所以是幂等的;而POST
请求不是幂等,因为它修改了数据,每一次请求都会再次造成副作用。
上面列举的这些区别,实际上有一些是存在因果关系的,比如POST
用来请求服务器修改数据,所以每一次POST
请求在理论上都会对服务器的数据进行修改,正因为如此,才有了这几条:
- 刷新时需要重新提交数据,以获取最新的资源;
- 不可缓存,因为
POST
请求会修改资源,所以缓存旧资源没有意义;
浏览器将GET
请求的数据放入URL
中,而POST
请求的数据放入body
中,所以才有了下面几条:
POST
请求更加安全,因为GET
请求直接将数据放入URL中,用户直接可以看到,但是POST
的数据放入body
中,用户无法直接看见;GET
请求的数据只允许ASCII
字符,因为数据在URL
中,URL
中只允许ASCII字符,而POST
数据放入body
中,body
中允许二进制数据;
但是,以上这些区别都是浏览器以及Web
服务器遵循HTTP
的约定实现的,并不是GET
和POST
的本质区别,下面我们从报文层面分析GET
和POST
的区别。
2.2 报文层面的区别
这里我直接给出结论:GET方法和POST方法本质没有太大区别,仅仅报文格式以及方法名称不同。不论是GET
方法还是POST
方法的报文,都是HTTP
报文,而HTTP
是基于TCP/IP
做数据传输的,也就是说,在传输层,这两种方法的报文传输方式没有任何的区别。在约定中,GET
方法的数据被放入URL
,而POST
报文的数据被放入body
就是格式上的区别,但是这也不是绝对的。
2.3 深入理解它们的区别
下面我就从本质层面来说明对以上所说的区别做一个解读:
(1)GET方法用来向服务器请求资源,而POST方法请求服务器修改数据
这一点正是HTTP
规范中对这两个方法的约定,但是,仅仅只是约定,并不是强制。也就是说,我们完全可以通过GET
方法请求服务器修改数据,而通过POST
方法向服务器请求资源。对于很多Web
开发的初学者,应该都干过类似的事情,比如做使用Servlet
或者SpringMVC
做Web
开发,混用GET
与POST
。所以说,对于这一条区别,并不是一定的。
(2)GET方法数据被放入URL,而POST放入body
这是也是HTTP
规范对这两种方法报文的约定,而浏览器在创建请求报文时是遵照这个约定实现的,仅此而已。这也就是说,对于GET
请求,我们也可以将数据放入body
中,而对于POST
的数据,我们也能够放入URL
中。我们违反这个约定,报文依旧可以正常传输,只要服务器的实现支持,就能够正常的获取数据。
(3)GET方法发送的数据有限制(长度和类型),而POST没有
我们前面说过,GET
方法只能发送ASCII
字符数据,且数据的长度是有限制的,而POST
可以发送二进制的数据,且长度没有限制。首先从数据类型来说,不是GET
方法只能发送ASCII
字符数据,而是URL
中只能放入字符数据,而GET
方法的数据被放入URL
,自然只能被URL
所限制。如果我们在GET
报文的body
中放入数据,照样能够放入二进制数据。再来说说数据长度,HTTP
规范中并没有限制URL
的长度,真正限制URL
长度的是浏览器,浏览器为了方便处理数据,以及安全性考虑,对URL
的长度做了限制。但是,HTTP
规范并没有限制URL
长度,我们完全可以通过编写代码的方式,创建一个包含很长很长的URL
的HTTP
报文,是可以正常传输的。
(4)POST方法比GET方法更加安全
这种说法的依据就是浏览器不会把POST
的数据放入URL
,用户不能直接看见,所以认为POST
更加安全。但是在数据传输的过程中,GET
和POST
的报文传输是没有区别的,都是通过TCP
连接进行传输。只要我们通过抓包软件,抓取到了HTTP
报文,其实它们携带的数据都是直接可见,没有任何安全性可言。所以,从严格意义上来讲,GET
和POST
的安全性没有太大区别。若想要安全,应该使用HTTPS
。
(5)POST请求会发送两个TCP报文
网上还流传着它们之间的另一个区别,就是说浏览器会将POST
请求的header
和body
分开来发送,产生两个TCP
报文段,先发送header
,接收到服务器响应的状态码100
之后,再发送body
部分。但是,HTTP
规范中并没有明确说明这一点,而且在实际的测试中,也没有发生这种情况。所以可以认为,这只是某些浏览器的自主实现,并不是POST
的必然行为。
三、总结
我们谈论GET
和POST
的区别时,应该像上面一样,分情况进行讨论。在浏览器层面,它们之间有许许多多的区别,有些是HTTP
规范的约定,而大部分其实还是浏览器的自主实现;而从本质上来看,两种其实没有太大区别。