HTTP的缓存机制
缓存是一种保存资源副本到客户端中并且在下次请求时直接使用该副本的技术
缓存不是永久的 缓存是为了解决多次访问时请求相同的东西 而产生的对服务器的压力 使用缓存 让第一次访问的东西 暂时存放在客户端中 在下一次访问时直接使用客户端中的 这个缓存 暂时存放的是由一定生命周期的 过期就失效 失效后 再次访问 就要重新向服务器请求
缓存的优势
减小服务器消耗和运行压力
减小服务器资源加载延迟
减小对带宽的压力
Web站点变更具有响应性
缓存应用
常见的HTTP缓存只存放GET响应,对其他类型的响应则无能为力
普遍会缓存案例:
检索请求的成功响应:响应状态码为200
不变的重定向:响应状态码为301
错误响应:响应状态码为404的一个页面
不完全的响应:响应状态码为206,只返回局部信息
除了GET请求外,如果匹配到作为一个已经被定义的cache键名的响应
缓存的类型
私有缓存
私有缓存只能用于单独用户
Cache-Control:private
共享缓存
共享缓存可以被多个用户使用
Cache-Control:public
缓存控制
Cache-Control头 HTTP/1.1
Cache-Control头属于通用头 但是大多数情况用在响应头
Cache-Control头专门区分对缓存机制的支持情况
禁止进行缓存(比如网上银行) 安全性要求高的就要禁止缓存
Cache-Control:no-store
Cache-Control:no-cache(在服务器验证允许的情况下,才能用本地的缓存),no-store,must-revalidate
强制确认缓存
Cache-Control:no-store(彻底的不允许使用本地缓存,只能去服务器查)
缓存过期机制
Cache-Control:max-age=时间(单位为毫秒)
s-maxage=时间(专门为代理服务器去设置的)
max-stale=时间(就算在max-age过期了但是在max-stale没过期还是能用 浏览器中用不了 只有发起端能用)
如果设置的缓存过期时间没超过之前 我们在服务器更改了内容 浏览器也会去用本地缓存 这样就有问题了
解决他一般用哈希码 就是通过计算出的对内容的一串码 如果内容不变就不会改变他的哈希码 吧这个作为if条件就能知道要不要用本地缓存 也不会很大的影响速度
缓存验证确认
Cache-Control:must-revalidate
Pragma头 HTTP/1.0
与Cache-Control相同 只不过支持的HTTP版本不同 浏览器兼容不同
Pragma:no-cache == Cache-Control:no-cache
Expires头
Expires头包含日期/时间,就是在这个时间后 响应过期
无效的日期 比如0表示过期的日期 就是资源过期
如果在Cache-Control头中设置’max-age’或者’s-max-age’ Expires会被忽略
Expires:Wed,21 Oct 2015 07:28:00 GMT
Cookie
Secure只会在https的时候发送
HttpOnly无法通过document.cookie访问
Cookie解决HTTP协议的无状态问题
Cookie是服务器发给客户端浏览器并保存在本地的一小块数据,并且在下一次访问时携带该数据发给服务器
浏览器第一次访问服务器并请求数据 --> 服务器响应浏览器,并且向浏览器发送请求的数据并且携带Cookie数据 --> 浏览器接收到后会把Cookie存储到客户端本地–> 当再次访问该服务器时,发送请求并且携带本地的Cookie --> 服务器接收Cookie并且响应请求的数据 --> 如此往返
1.服务器建立Cookie (浏览器第一次访问服务器)
2.服务器发送Cookie
3.浏览器接收Cookie,浏览器储存Cookie
4.浏览器发送Cookie(浏览器非第一次访问服务器)
5.服务器接收Cookie
现在浏览器现在出现了各种各样的储存方法 cookie逐渐淘汰
Cookie的作用域
Domain和Path标识定义了Cookie的作用域,即Cookie应该发送给那些URL
如果不指定,默认为当前文档的主机(不包含子域名)
如果指定Domain,一般包含子域名
Domain = XXXXX.com 则Cookie也包含子域名
Path标识指定了主机先的那个路径可以接受Cookie,用字符‘%x2F’("/")作为路径分隔符
Cookie的有效期
Max-Age和Expires标识定义了Cookie的有效期
会话期Cookie
存储在浏览器中 关闭浏览器就消失 不需要Max-Age和Expires
持久性Cookie
存储在客户端的电脑中 关闭浏览器也会存在 这个可以定义生存时间
需要Max-Age和Expires
Cookie的应用
会话状态控制(购物车,用户登录状态等)
个性化设置(主题等)
浏览器行为跟踪
缓存
服务器
const http = require('http');
const fs = require('fs');
http.createServer(function(req,res){
console.log('requset come',req.url);
if(req.url === '/'){
const html = fs.readFileSync('test.html','utf-8');
res.writeHead(200,{
'Content-Type':'text/html'
});
res.end(html)
}
if(req.url === '/script.js'){
res.writeHead(200,{
'Content-Type':'text/javascript',//设置内容的类型 职位text/JavaScript 就会把内容当做js允许
'Cache-Control':'max-age=200'//是指本地缓存 什么是过期
});
res.end('console.log("xxxxxxxx")');//这个就是发送的内容
}
}).listen(8888);
// http://127.0.0.1:8888/
客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script src="/script.js"></script>
</html>
资源验证
缓存如何验证 查找
验证头
Last-Modified 上次修改时间
配个If-Modified-Since(通常用这个)或者 If-Unmodified-Since(很少会用到)使用
原理是 通过服务器的上次修改时间和客户端的上次修改时间对比 如果一致就没问题 如果不一致就要更新资源
Etag
配合If-Match或则If-Non-Match使用
数据签名 就是类似计算哈希值,得到签名 用这个标记这个资源 对比签名如果不一样就表示需要更新缓存
服务器
const http = require('http');
const fs = require('fs');
http.createServer(function(req,res){
console.log('requset come',req.url);
if(req.url === '/'){
const html = fs.readFileSync('test.html','utf-8');
res.writeHead(200,{
'Content-Type':'text/html'
});
res.end(html)
}
if(req.url === '/script.js'){
res.writeHead(200,{
'Content-Type':'text/javascript',//设置内容的类型 职位text/JavaScript 就会把内容当做js允许
'Cache-Control':'max-age=20000000,no-cache',//max-age=20000000是指本地缓存 什么是过期 no-cache的意义是说明虽然允许使用本地缓存但是需要跟服务器验证
'Last-Modified':'123',
'Etag':'777',
});
const etag = req.headers['if-none-match'];
if(etag === '777'){
res.writeHead(304,{ //304状态码就代表not modified 就是没有修改缓存
'Content-Type':'text/javascript',
'Cache-Control':'max-age=20000000,no-cache',//去掉no-cache 会直接用本地缓存 不会像服务器验证 +no-store 就是直接屏蔽所有的本地缓存 有也不能用
'Last-Modified':'123',
'Etag':'777',
});
res.end('555')
}
else{
res.end('console.log("xxxxxxxx")');//这个就是发送的内容
}![在这里插入图片描述](https://img-blog.csdnimg.cn/20200824203032426.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ5MjI3NQ==,size_16,color_FFFFFF,t_70#pic_center)
}
}).listen(8888);
// http://127.0.0.1:8888/
客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script src="/script.js"></script>
</html>