目录结构
代码
const http = require('http')
const url = require('url')
const path = require('path')
const { stat, readFile } = require('fs/promises')
const crypto = require('crypto')
/**
* 强制缓存对跟文件是没有作用的 也就是html文件
*
*/
// stat 读取路径
http
.createServer(async (req, res) => {
let { pathname } = url.parse(req.url)
// console.log(pathname)
// console.log(path.join(__dirname, '../', pathname, 'static/index.html'))
let fileName =
pathname === '/'
? path.join(__dirname, '../', pathname, 'static/index.html')
: path.join(__dirname, '../', pathname)
// console.log(fileName)
// 强制缓存 老版本 兼容性强
// Cache-Control的优先级比expires 同时存在时,只有Cache-Control生效。
// res.setHeader('Expires', new Date(new Date().getTime() + 1000 * 10).toGMTString()) // 除了根文件之外的所有文件全部被缓存 不会第二次加载 时间一过 就会加载
/* 是一个绝对值
10 秒之内拿到的全是除根文件 的缓存文件
*/
// 强制缓存 新版本
// res.setHeader('Cache-Control', 'max-age=10') // max-age 后面数字直接为秒 是相对值
/**
* max-age=no-cache并不意味着不缓存。它的意思是在使用缓存资源之前,它必须经过服务器的检查(revalidate也可以实现这个功能)。(缓存 但是不用这个缓存)
max-age=no-store才是告诉浏览器不要缓存它。此外,must-revalidate并不意味着必须重新认证,它的前提是资源还在max-age的缓存期内,否则必须重新认证。(不缓存)
*
*/
try {
const statObj = await stat(fileName)
console.log(statObj.ctime)
// 协商缓存
/**
* Last-Modified/If-Modified-Since和Etag/If-None-Match,其中Etag/If-None-Match的优先级比Last-Modified / If-Modified-Since高。
*/
/*
atime 创建时间
mtime 修改时间
ctime 任何东西
*/
// 第一种
// const ctime = statObj.ctime.toGMTString()
// res.setHeader('Last-Modified', ctime) // 根据秒的方式
// if (req.headers['if-modified-since'] === ctime) {
// return (res.statusCode = 304) && res.end()
// }
if (statObj.isFile()) {
let rresult = await readFile(fileName)
// 第二种
const hash = crypto.createHash('md5').update(rresult).digest('base64') // base64 传输
// console.log(rresult.toString())
// console.log(fileName) // 每次刷新会请求三次 文件 html css js
res.setHeader('Etag', hash)
if (req.headers['if-none-match'] === hash) {
return (res.statusCode = 304) && res.end()
}
res.end(rresult)
} else {
res.statusCode = 404
res.end('NOT FOUND')
}
} catch (err) {
res.statusCode = 404
res.end('NOT FOUND')
}
})
.listen(3000)