超文本传输协议HTTP
的设计目的是保证客户端与服务端之间的通信,HTTP
协议的工作方式是客户端与服务端之间的请求响应,在客户端与服务端进行请求响应时最常用的两种方法就是GET
与POST
。
GET
是安全的、幂等的,而POST
是 不安全的、不幂等的。GET
在浏览器回退或者刷新时是无害的,而POST
会再次提交数据请求。GET
产生的URL
地址可以作为书签保存,而POST
不行。GET
请求会被浏览器主动cache
,而POST
不会主动缓存。GET
请求只能进行url
编码,而POST
支持多种编码方式。GET
请求参数会被完整保留在浏览器历史记录里,而POST
中的参数不会被保留。GET
请求在URL
中传送的参数长度受URL
长度限制,而POST
的大小取决于后端配置。GET
参数只接受ASCII
字符的数据类型,而POST
没有限制,可以传输二进制数据。GET
比POST
更不安全,因为参数直接暴露在URL
上,所以不适合传递敏感信息。GET
参数通过URL
传递,直接可见,POST
的参数放在Request body
中,不直接可见。
上述的区别都是GET
与POST
在浏览器中的具体实现上的区别,例如现在广泛使用的Promise
就是各种对于Promise/A+
的规范promisesaplus.com
的实现,在HTTP/1.1
的规范的征求意见稿RFC
中提到了语义这个词语,语义定义了一个类型的请求应该具有什么样的,例如GET
的语义就应该是获取资源,POST
的语义就是修改资源,如果在符合语法的前提下实现违背语义的行为也是可以做到的,例如使用GET
修改资源或者使用POST
获取资源,甚至使用GET
发送body
(这需要服务端能够配合解析),这是合法的请求但是这是不符合语义的请求,而且很有可能会带来一些副作用,所以在本质上GET
与POST
的区别是其语义的区别,甚至可以理解为GET
与POST
并没有什么区别,只要客户端与服务端能够配合发送与接收即可,一个敢发一个敢收就可以了,而上文所述的区别主要是在浏览器中具体实现上的区别。
关于安全性与幂等性,安全性是指访问接口时不会对服务端资源状态发生改变,幂等性是指对于同一接口的URI
多次访问时,得到的资源状态是相同的。
GET
: 安全的,幂等的,用于读取资源。POST
: 不安全的,不幂等的,用于服务端自动产生的实例号创建资源,更新部分资源。PUT
: 不安全的,幂等的,用于客户端的实例号创建资源,更新资源。DELETE
: 不安全的,幂等的,用于客户端实例号删除资源。
在浏览器点击后退操作时,如果将要返回的页面是GET
请求的,那么将会安全的进行回退,如果将要返回的页面是POST
请求的,例如使用<form>
的method
为POST
去提交数据并跳转页面的话,浏览器会发出一个是否再次提交表单的确认提示。
关于GET
和POST
提交的参数长度的限制问题,GET
是通过URL
提交数据,因此GET
可提交的数据量就跟URL
所能达到的最大长度有直接关系,实际上HTTP
协议对URL
长度是没有限制的,但是在各种浏览器中对于URL
长度是有限制的,而且限制的长度是不同的,一般使用不超过4K
,此外服务端也会对于URL
有各自的限制,当然服务端可以接收的URL
长度大小是可以配置的,同样的,HTTP
协议没有对POST
进行任何限制,POST
提交的数据大小一般是受服务器的主动配置来限定大小。
关于敏感信息不要使用GET
进行传输主要有两个方面的考虑,首先使用GET
传输敏感信息会直接暴露在URL
上,会直接可见,此外使用GET
传输的参数会被直接保存在浏览器的历史记录中以及服务器的日志中,当然HTTP
协议本身就是一个明文传输的协议,无论是使用GET
还是POST
在中间人攻击等情况下都是能够拿到传输的数据的,如果需要避免中间人等攻击需要使用HTTPS
进行数据的加密传输。
关于GET
发送一个请求,POST
发送两个请求的问题,同样这也是各种浏览器对于HTTP
协议的具体实现的案例,而不涉及GET
和POST
的本质区别,关于这个具体的实现在各种浏览器上的表现并不相同,主要是浏览器的网络请求底层对于请求上优化的实现,例如需要使用POST
传输一个大文件,那么浏览器就有可能首先发送一个数据包并携带少量数据去检测服务端是否能够接收这个文件,服务端在解析上传的文件时,总是会先完全解析全部的请求头部,服务器端总是希望能够了解请求的控制信息后,就能决定这个请求怎么进一步处理,是拒绝还是接收,如果服务端允许接收这个文件那么客户端会继续发送数据进行上传操作,如果服务端拒绝了就直接中断上传,这样用以节省提高数据吞吐和降低带宽的浪费。在本质上这和HTTP
协议无关,这是浏览器在具体实现上做的一些优化,例如在内部设定一次POST
的数据超过1KB
就先只发请求头,否则就一次性全发,客户端甚至还可以做一些Adaptive
的策略,统计发送成功率,如果成功率很高,就总是全部发等等。不同浏览器可以有各自的不同的方案,不管怎样做,优化目的总是在提高数据吞吐和降低带宽浪费。无论浏览器如何发送其总是符合HTTP
协议的,是具体实现而不涉及GET
和POST
的本质区别。
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/25028045
https://www.zhihu.com/question/28586791
https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4