http缓存
2019-10-29 本文已影响0人
成熟稳重的李先生
http缓存分为两种, 强制缓存(网站首页不能做缓存)和对比缓存。
// cache.js
let http = require("http")
let mimie = require("mime"); //第三方模块,用于添加content-type
let url = require("url");
let path = require("path");
let fs = require("fs");
/ *
* 首页的html文件可以使用对比缓存
* 第一次访问的时候,设置一个头, “last-modified”--最后的修改时间
* 下次在请求的时候,带上这个时间,看是否一致
*/
http
.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
let absPath = path.join(__dirname, pathname);
// js,css文件之类的, 每次更改了,就要重新请求,-----这是对比缓存
/*
* 强制缓存(如果服务器上文件修改了,但是每到缓存失效的时间,
* 那么浏览器端不会更新,因此强制缓存是有局限性的)
* 这种缓存只针对像js,css,img这类的文件
*/
res.setHeader("Cache-Control", "max-age=5"); //相对时间,单位是秒
res.setHeader("Expires", new Date(Date.now() + 5000).toUTCString()); // 绝对时间
fs.stat(absPath, (err, statObj) => {
if (err) {
res.statusCode = 404;
res.end(`Not Found`);
}
if (statObj.isFile()) {
let ctime = statObj.ctime.toUTCString();
/*
* 对比缓存分两种:
* 1). last-modified(最后修改时间)
*/
/*
* if-modified-since是浏览器自己携带的,
* 如果服务器设置过last-modified,那么下次请求就会带上“if-modified-since
* 缺陷:1)如果文件没变,但是时间改了
* 2) 时间精确到秒,可能会有问题
*/
if (req.headers["if-modified-since"] == ctime) { // 如果时间没变,设置304
res.statusCode = 304;
res.end();
return;
}
res.setHeader("Last-Modified", ctime); //最后修改时间
/*
* 2). Etag(摘要)
* Etag的方式比较靠谱,但是不能对大文件进行摘要文件Etag,可以采用“文件大小+文件的最后修改时间”来组成Etag
*/
let md5 = crypto.createHash("md5");
let rs = fs.createReadStream(absPath);
let arr = []; //要先写入响应头,再写入响应体
rs.on("data", function(data) {
md5.update(data);
arr.push(data);
});
rs.on("end", () => {
let etag = md5.digest("base64");
// "if-none-match"和"Etag"是一对,响应头如果设置了“Etag”,那么请求会带上“if-none-match”
// 两者进行对比,得出是否需要走缓存
if (req.headers["if-none-match"] === etag) {
res.statusCode = 304;
res.end();
return;
}
res.setHeader("Etag", etag);
res.end(Buffer.concat(arr));
});
res.setHeader("Content-Type", mime.getType(absPath) + ";charset=utf-8");
fs.createReadStream(absPath).pipe(res);
}
// 一般情况下,这两种缓存都使用,访问服务器时,会先加一个强制缓存,强制缓存n秒
// n秒过后,会在发送请求时使用对比缓存,先判断last-modified和if-modified-since,Etag和if-none-match,
// 如果都成立,则返回304,再强制缓存n秒
// 如果有变化,返回新的文件
// 304 = last-modified + if-modified-since 和 Etag + if-none-match(强制缓存不属于304)
});
})
.listen(3000);