HTTP–GET和POST的区别
总结自《图解HTTP》& GET 和 POST 到底有什么区别?
在讨论这个问题之前正好复习一下,HTTP协议的相关问题。
来嘛,先复习一遍计网基础知识:
OSI 七层模型,自下而上:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
TCP/IP 四层模型:数据链路层、网络层、传输层、应用层
常见的协议(基于 TCP \ IP 模型):
- ARP、IP、ICMP 协议都是网络层
- TCP、UDP 为传输层协议
- HTTP、FTP、DNS 等都为应用层协议
- 链路层主要就是:网卡、网络适配器等硬件设施
HTTP 协议即超文本传输协议
,这个 “超” 字意思是它不止能传输文字,还可以传输文件、图片、音频等,用于客户端和服务端之间的通信。那么就必有一端是客户端一端是服务器端。
GET
GET 多用于请求获取一个 html 页面/图片/css/js 等资源,是 “读取” 资源的,反复读取不会对访问的数据有副作用,也就是不会修改数据,这被称为 幂等性
。
因为 GET 是读取,那么就可以对 GET 请求进行缓存,这个缓存可以做到浏览器上,也可以交给(缓存)代理服务器上(如 nginx ),或者做到 server 端。
POST
在页面中的 <form> 标签会定义一个表单,那么这个表单可以由 submit 提交给服务器,这种 POST 请求对服务器往往是有副作用的,增加数据或者修改数据、删除数据,是不幂等的。
那么不幂等就意味着没有办法缓存,你不能上次下单成功了这次还想下单,服务器直接把缓存中的成功下单页面给你,这是不符合逻辑的。你不能把他储存为书签,点一下一个 POST 就下一个单。
GET和POST携带数据的格式也有区别。当浏览器发出一个GET请求时,就意味着要么是用户自己在浏览器的地址栏输入,要不就是点击了html里a标签的href中的url (这里的 URL 中的中文只是让用户体验更好而已,实际上都要经过 URL编码翻译为真正的 URL 才能发给服务器,而且这里的长度也有限制 2kb)。所以其实并不是GET只能用url,而是浏览器直接发出的GET只能由一个url触发。所以没办法,GET上要在url之外带一些参数就只能依靠url上附带querystring。但是HTTP协议本身并没有这个限制。
浏览器在POST一个表单时,url上也可以带参数,只要 <form action=”url” > 里的 url 带 querystring 就行。只不过表单里面的那些用 <input> 等标签经过用户操作产生的数据都在会在body里。
因此我们一般会泛泛的说“GET请求没有body,只有 url ,请求数据放在 url 的 querystring 中;POST请求的数据在body中“。但这种情况仅限于浏览器发请求的场景。
总结
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET编码类型application/x-www-form-url,POST编码类型encodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET对数据长度有限制,当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。POST无限制。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。其实一样 http 明文传输
- GET参数通过URL传递,POST放在Request body中。
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 GET和POST还有一个重大区别,简单的说:GET产生一个TCP数据包;POST产生两个TCP数据包。
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。