浏览器存储HTTP中的URL长度限制、cookie、sessionStorage和localStorage的区别和使用
一、背景
1.1 问题描述
最近发现陈年旧码业务中有这样一种场景,从一个页面A点击【批量审核】后,跳转到审核详情页面B,B页面直接报警了,很多接口直接413了;如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cRqUyfBa-1655371951280)(https://myimg-1302777074.cos.ap-beijing.myqcloud.com/image-20220614212549251.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JNLWdqWA-1655371951282)(https://myimg-1302777074.cos.ap-beijing.myqcloud.com/image-20220614212650152.png)]
再来看看B页面链接如下:这个data参数数据量太大了竟然还用url参数传递
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3tgCq2JE-1655371951282)(https://myimg-1302777074.cos.ap-beijing.myqcloud.com/image-20220616160647908.png)]
1.2 问题分析
一看页面链接就觉得这链接参数传递不合理:为啥不合理,这里涉及知识点如下:HTTP中的url长度是否有限制?限制是多少?到底是哪里限制了URL的长度和大小?url限制大小那还能选择别的方案么?后端不添加接口的情况下,前端自己用什么方案搞定?
HTTP中的URL长度限制
HTTP协议不对URI的长度作事先的限制,服务器必须能够处理任何他们提供资源的URI,并且应该能够处理无限长度的URIs,这种无效长度的URL可能会在客户端以基于GET方式的请求时产生。如果服务器不能处理太长的URI的时候,服务器应该返回414状态码(此状态码代表Request-URI太长)。各浏览器的url传值的长度限制解决办法
说明当时前端技术方案选型存在问题,没有考虑周全;
注:服务器在依赖大于255字节的URI时应谨慎,因为一些旧的客户或代理实现可能不支持这些长度。
虽然协议中未明确对url进行长度限制,但在真正实现中,url的长度还是受到限制的,一是服务器端的限制,二就是游览器端的限制。
一、服务器端
在服务器端,主要是apache,jboss和nginx等,我在网上找到的调节方法可以参加下文:关于http请求url长度以及请求消息体长度的研究(一)(服务器端) :
nginx :设置参数:large_client_header_buffers,该参数对nginx服务器接受客户端请求的头信息时所分配的最大缓冲区的大小做了限制,也就是nginx服务器一次接受一个客户端请求可就收的最大头信息大小。这个头不仅包含 request-line,还包括通用信息头、请求头域、响应头域的长度总和。这也相当程度的限制了url的长度。 nginx服务器默认的限制是4K或者8K,这是根据服务器的硬件配置有关的,一般为内存一页的大小,目前大部分为4K,即4096字节。
nodejs:nodejs的http服务,设置url长度限制和headers的大小还是相对比较灵活的,用url.length来限制
二、游览器端
游览器的种类繁多,并且对URL的长度限制是有所差异的,具体如下:
游览器 | 最大长度(字符数) | 备注 |
---|---|---|
Internet Explorer | 2083 | 如果超过这个数字,提交按钮没有任何反应 |
Firefox | 65,536 | |
chrome | 8182 | |
Safari | 80,000 | |
Opera | 190,000 | |
curl(linux下指令) | 8167 |
再看看陈年旧码,审核详情页面B要用到页面A中被选中的要审核的信息,于是发现小旧同学应该是在做这个需求时候没有做好技术方案选型,用的方法是直接通过跳转url+参数形式,直接把B页面需要的参数从A页面带过去了,所以技术选型真的很重要,解决问题前不能只是实现功能逻辑就可以的,所涉及到的知识都要了解清楚,才能选择出最佳方案。分析完问题后,我们发现用url携带这么大量的参数到下一个页面是不可取的,那针对这个场景到底应该用什么来实现我想要的效果且是合理的没有其他问题及隐患的方案呢?这里面就涉及到怎么把A页面的数据存起来,在B页面使用呢?于是要用到cookie、sessionStorage和localStorage,但是到底要选哪个?如下:
二、概念
浏览器存储:cookie,localStorage,sessionStorage
Cookie :Cookie 是小甜饼的意思。顾名思义,cookie 确实非常小,它的大小限
制为 4KB 左右。它的主要用途有保存登录信息,比如你登录某个网站市
场可以看到“记住密码”,这通常就是通过在 Cookie 中存入一段辨别用
户身份的数据来实现的。
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除。
sessionStorage 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。
三、比较
对比项 | cookie | localStorage | sessionStorage |
---|---|---|---|
生命周期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
大小 | 4K左右 | 一般为5MB | 一般为5MB |
与服务器端通信 | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 | 仅在客户端(即浏览器)中保存,不参与和服务器的通信 |
使用方法 | 自行封装 | 源生可用Storage.getItem() and Storage.setItem() | 源生可用// 保存:sessionStorage.setItem(‘key’, ‘value’); //获取数据: sessionStorage.getItem(‘key’); // 从 sessionStorage 删除保存的数据: sessionStorage.removeItem(‘key’); // 从 sessionStorage 删除所有保存的数据 sessionStorage.clear(); |
通过对比发现,此类场景更适合用localStorage。因为需要存储的数据量大有超过4k的情况,但是不会大于5MB,所以选sessionStorage或者localStorage,但是sessionStorage关闭页面或者浏览器后就会被清除,为了防止审核员关闭后又重新打开时候取不到数据,所以最终选择了localStorage。下面是各个方案的使用案例
四、使用
localStorage这个方案是最适合我们这个问题,但是还有没有其他隐患问题呢?有的,因为审核员可能一次打开多个审核详情页面B,这个时候浏览器每次存的都是最后一次的localStorage存储的值,也就是说尽管打开了多个审核详情页B,所取到的A的存储信息localStorage值都是一样的。
那这个问题前端就没法解决了么?可以采取其他方案:前后端一起改造这个问题,进入详情页B时候先调用一个接口去取这些要存的数据,不通过前端存,而是存在后端接口,当然这个方法前面没有用是因为这是比较常规的方案需要后端配合,改动多比较耗时,这里主要是展示分析问题的过程中对于知识点的整理以防后面忘记或者记得不清晰,方便及时查看,这是个比较简单常见的问题,但是如何技术选型时候尽管知道有这个东西有时候具体的参数值是记不住的,这里面对比记录方便后续查看。
localStorage
这个使用细节直接给个demo,其他扩展请自行去MDN查看
window.localStorage
// 保存数据语法:
localStorage.setItem("key", "value");
// 读取数据语法:
var data = localStorage.getItem("key");
// 删除数据语法:
localStorage.removeItem("key");
// 移除所有
localStorage.clear();
//下面的代码片段访问了当前域名下的本地 Storage 对象,并通过 Storage.setItem() 增加了一个数据项目。
localStorage.setItem('myCat', 'Tom');
//该语法用于读取 localStorage 项,如下:
let cat = localStorage.getItem('myCat');
//该语法用于移除 localStorage 项,如下:
localStorage.removeItem('myCat');
//该语法用于移除所有的 localStorage 项,如下:
// 移除所有
localStorage.clear();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Scyx9KF-1655371951283)(https://myimg-1302777074.cos.ap-beijing.myqcloud.com/image-20220614220240409.png)]
sessionStorage
这个使用细节直接给个demo,其他扩展请自行去MDN查看
// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');
// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');
// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');
// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();
// 获取文本输入框
let field = document.getElementById("field");
// 检测是否存在 autosave 键值
// (这个会在页面偶然被刷新的情况下存在)
if (sessionStorage.getItem("autosave")) {
// 恢复文本输入框的内容
field.value = sessionStorage.getItem("autosave");
}
// 监听文本输入框的 change 事件
field.addEventListener("change", function() {
// 保存结果到 sessionStorage 对象中
sessionStorage.setItem("autosave", field.value);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IYExqtQj-1655371951283)(https://myimg-1302777074.cos.ap-beijing.myqcloud.com/image-20220614220225639.png)]
cookie封装
//设置cookie
function setCookie(json, time) {
var data = new Date(new Date().getTime() + time * 24 * 60 * 60 * 1000).toUTCString()
for (key in json) {
document.cookie = key + "=" + json[key] + ";expires=" + data
}
}
//获取cookie
function getCookie(attr) {
return document.cookie.match(new RegExp("(^|\\s)" + attr + "=([^;]+)(;|$)"))[2]
}
//删除cookie
function removeCookie(attr) {
var json = {};
json[attr] = "";
setCookie(json, -1);
总结
通过一个业务问题,梳理了HTTP中的URL长度限制、cookie、sessionStorage和localStorage的区别和使用,希望能帮助到需要的小伙伴儿
感谢阅读
本文资料参考自:MDN和原文中引入的外链文章
- 1[cookie、sessionStorage和localStorage的区别和使用]: https://blog.csdn.net/flhhly/article/details/123635981
- 2[HTTP中的URL长度限制]:https://www.cnblogs.com/lengyuhong/archive/2012/02/04/2330130.html
- 3[各浏览器的url传值的长度限制解决办法]:https://blog.csdn.net/liaonanfeng88/article/details/103470741
- 4[MDN]:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/localStorage
❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章
关注公众号小圆脸儿
,一个专注于web前端基础、工程化、面试的前端公众号