美文网首页
http缓存

http缓存

作者: 成熟稳重的李先生 | 来源:发表于2019-10-29 23:47 被阅读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);
    

    相关文章

      网友评论

          本文标题:http缓存

          本文链接:https://www.haomeiwen.com/subject/pbcnvctx.html