HTTP请求方法GET和POST
HTTP请求方法GET和POST的区别,出现在面试题目中,网上也有很多总结。但是多看看RFC2616和RFC7321就发现那些总结有些问题。
一般理解
下面是普遍的理解,来自w3school的整理
GET后退按钮/刷新无害,POST数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
GET书签可收藏,POST为书签不可收藏。
GET能被缓存,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没有限制。也允许二进制数据。
与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
GET的数据在 URL 中对所有人都是可见的。POST的数据不会显示在 URL 中
误解分析
- 响应是否能够缓存,是由响应中的缓存相关首部决定的,比如Cache-Control和Expire。并不是由方法get或者post决定是否可以缓存,虽然基本上都是缓存get请求的响应,设计get方法概念上就是用来获取信息的
- 长度限制,本质上是因为GET方法请求参数附着于URL上,POST提交的数据在HTTP请求体中。虽然可以说是不同点,但是更多的是关于URL和HTTP的不同,两个有关系但是没有对比性
- 编码也是,是URL采用的ASCII编码,而HTTP请求体编码有多种选择
- 安全性问题的第一个解释是,get请求和post请求,一个主要用来获取信息,一个主要用来提交信息。RFC7321中的请求方法规范的安全性,只获取信息的get方法更具有安全性。
- 安全性的第二个问题是,HTTP请求本身是明文传递的,所以无论是URL带请求参数或者HTTP请求体,都是不安全的。只是获取报文比直接读取URL稍微复杂一点。如果解决安全性,要使用SSL/TSL进行加密才可以。
正确认识
HTTP方法的特征
安全性
如果方式是只读的,则被认为是“安全的”方法。客户端向服务端的资源发起的请求如果使用了是安全的方法,就不应该引起服务端任何的状态变化,因此也是无害的。 此RFC定义,GET, HEAD, OPTIONS 和 TRACE 这几个方法是安全的。
但是这个定义只是规范,并不能保证方法的实现也是安全的,服务端的实现可能会不符合方法语义,正如上文说过的使用GET修改用户信息的情况。
引入安全这个概念的目的是为了方便网络爬虫和缓存,以免调用或者缓存某些不安全方法时引起某些意外的后果。User Agent(浏览器)应该在执行安全和不安全方法时做出区分对待,并给用户以提示。
引入安全这个概念的目的是为了方便网络爬虫和缓存,以免调用或者缓存某些不安全方法时引起某些意外的后果。User Agent(浏览器)应该在执行安全和不安全方法时做出区分对待,并给用户以提示。
幂等性
幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同。按照RFC规范,PUT,DELETE和安全方法都是幂等的。同样,这也仅仅是规范,服务端实现是否幂等是无法确保的。
引入幂等主要是为了处理同一个请求重复发送的情况,比如在请求响应前失去连接,如果方法是幂等的,就可以放心地重发一次请求。这也是浏览器在后退/刷新时遇到POST会给用户提示的原因:POST语义不是幂等的,重复请求可能会带来意想不到的后果。
引入幂等主要是为了处理同一个请求重复发送的情况,比如在请求响应前失去连接,如果方法是幂等的,就可以放心地重发一次请求。这也是浏览器在后退/刷新时遇到POST会给用户提示的原因:POST语义不是幂等的,重复请求可能会带来意想不到的后果。
可缓存性
可缓存性 顾名思义就是一个方法是否可以被缓存,此RFC里GET,HEAD和某些情况下的POST都是可缓存的,但是绝大多数的浏览器的实现里仅仅支持GET和HEAD。关于缓存的更多内容可以去看RFC7234。
总结
GET的语义是请求获取指定的资源。GET方法是安全、幂等、可缓存的(除非有 Cache-ControlHeader的约束),GET方法的报文主体没有任何语义。
POST主要用来提交信息,用于更新或新建资源,数据包含在请求主体中。POST方法不安全,不幂等,(大部分实现)不可缓存(不实现)。
兼容
IE浏览器中,jquery使用$.get()发送请求,浏览器会缓存请求结果。缓存有时候可用来加速响应,提高性能。但是有时候会使请求使用缓存的旧数据而无法从服务器获取最新的数据。
要解决问题,一种方式是禁止缓存;另一种方式是改变URL
Jquery
在请求中声明禁止使用缓存
$.ajax({ url: 'test.html', cache: false, success: function(html){ $('#results').append(html); } });
或者禁止所有请求使用浏览器缓存
$.ajaxSetup({cache: false}});
javascript
之所以能够使用缓存,是因为请求URL同之前的请求URL相同,所以为了能够获取最新数据,给URL添加时间戳、随机数
var img.src = 'www.hungred.com'+'?'+Math.random()*Math.random(); return $(img).load(function() { alert('completed!'); })
HTML
在HTML中使用meta等标签限制缓存
<meta http-equiv='cache-control' content='no-cache'> <meta http-equiv='expires' content='0'> <meta http-equiv='pragma' content='no-cache'>
参考