缓存验证Last-Modifie和Etag的使用

Posted wzndkj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缓存验证Last-Modifie和Etag的使用相关的知识,希望对你有一定的参考价值。

技术分享图片
看这张图,是浏览器发出请求到请求缓存到过程,这么一个原理

 

那么http里面如何进行验证呢?主要有两个验证到http头
Last-Modified(上次修改时间)
主要配合If-Modified-Since或者If-Unmodified-Since使用,什么意思呢,如果请求一个资源,资源返回上面有Last-Modified这个头,指定了一个时间,那么下次请求的时候,就会带上这个头,通过If-Modified-Since或If-Unmodified-Since,通常是使用If-Modified-Since,服务器通过If-Modified-Since对比上次给的Last-Modified,验证资源是否需要更新
Etag
这是一个更严格的验证,就是说我们的资源对他的内容会产生一个唯一的一个签名,也就是说,如果对这个资源的内容进行了修改,那么他的签名就会变成新的,最典型的做法就是对内容进行一个hash计算,下一次浏览器发起请求的时候就会带上If-Match或If-Non-Match使用,这个值就是服务端返回过来的Etag的值,然后服务端对比资源的签名判断是否使用缓存
// server.js
const http = require(‘http‘);
const fs = require(‘fs‘);

http.createServer(function(req,res){
  console.log(‘req come‘, req.url);
 
  if (req.url === ‘/‘) {
    const html = fs.readFileSync(‘test.html‘, ‘utf8‘);
    res.writeHead(200,{
      ‘Content-Type‘: ‘text/html‘
    })
    res.end(html);
  }
 
  if (req.url === ‘/script.js‘) {
    res.writeHead(200,{
      ‘Content-Type‘: ‘text/javascript,
      ‘Cache-Control‘: ‘max-age=2000000000, no-cache‘, // 缓存时间很长,但是下次请求时还是需要通过服务端验证
      ‘Last-Modified‘: ‘123‘,
      ‘Etag‘: ‘777‘
    })
    res.end(‘console.log("script loaded")‘);
  }
}).listen(8888);

console.log(‘server listening on 8888‘);
console.log(‘http://localhost:8888/‘)
<!--test.html-->
<body>
  <script src=‘/script.js‘></script>
</body>
技术分享图片

 

如图,浏览器发送了请求,服务端返回了,Cache-Control,Last-Modified:123,Etag:777,

 技术分享图片

再重新进行一次请求,发现,请求还是像服务端进行了请求,因为no-cache会到服务端验证,我们看request里面可以看到,带了If-Modified-Since:123,If-None-Match:777,但是这个内容其实没有做任何端更改,这个时候是希望浏览器不用返回实际的内容,只需要告诉我们去读缓存就可以,这个时候应该怎么做呢,这个时候需要再服务端做个判断
//server.js
const http = require(‘http‘);
const fs = require(‘fs‘);
 

http.createServer(function(req,res){
  console.log(‘req come‘, req.url);
  if (req.url === ‘/‘) {
    const html = fs.readFileSync(‘test.html‘, ‘utf8‘);
    res.writeHead(200,{
      ‘Content-Type‘: ‘text/html‘
    })
    res.end(html);
  }
 
  if (req.url === ‘/script.js‘) {
    console.log(req.headers);
    const etag = req.headers[‘if-none-match‘];
    if (etag === "777") {
      res.writeHead(304, {
        ‘Content-Type‘: ‘text/javascript‘,
        ‘Cache-Control‘: ‘max-age=2000000000, no-cache‘, // 缓存时间很长,但是下次请求时还是需要通过服务端验证
        ‘Last-Modified‘: ‘123‘,
        ‘Etag‘: ‘777‘
      })
      res.end(‘‘);
    } else {
      res.writeHead(200,{
        ‘Content-Type‘: ‘text/javascript‘,
        ‘Cache-Control‘: ‘max-age=2000000000, no-cache‘, // 缓存时间很长,但是下次请求时还是需要通过服务端验证
        ‘Last-Modified‘: ‘123‘,
        ‘Etag‘: ‘777‘
      })
      res.end(‘console.log("script loaded")‘);
    }
  }
}).listen(8888);

console.log(‘server listening on 8888‘);
console.log(‘http://localhost:8888/‘);

 

 技术分享图片

 

服务端做了修改,返回了304,但是response是返回有内容的,这是chrome缓存工具会读取出来,如果写一些新的内容,再请求,发现还是老的,所以读的是缓存里面的内容,把Disable cache钩上,就会发现请求新的数据了

 

以上是关于缓存验证Last-Modifie和Etag的使用的主要内容,如果未能解决你的问题,请参考以下文章

http缓存相关header

谷歌浏览器不会来回重新验证 etag

使用 ETag 和 Expires/Cache-control 的缓存策略,没有资产版本/ID

Chrome 会忽略 ETag 标头,只使用内存缓存/磁盘缓存

chrome 浏览器仅在使用 etag 和 last-modified-date 时才显示 200(来自磁盘缓存)

如何根据返回的 etag 使用 curl 缓存 api 响应?