HTTP状态码304详解

图和代码来源理解HTTP缓存和304状态码

下图是使用express启动了一个服务,启动之后浏览器访问两次localhost:8080所得请求、响应头

var express = require('express');
var app = express();

app.get('/', function(req, res) {
  res.send('hello world');
});
app.listen('8080')
第一次请求

在这里插入图片描述

第二次请求

在这里插入图片描述
从上面两次请求的请求和响应头发现,第二次请求localhost:8080时服务器返回的是304状态码。

之前了解过304状态码是当浏览器请求未改变且已缓存的资源时,服务器会返回304,告知浏览器,该资源从某个时间之后没有再改变,可以用在浏览器端缓存的资源。但具体304相关字段并未研究过,下来我们来看下304的相关内容。

1. HTTP缓存


web开发的优化阶段中,缓存是必不可少的一个因素,而其中HTTP缓存机制是Web性能优化的一个重要手段,善于利用HTTP缓存,能够大大提升Web页面的访问速度

2. 强缓存与协商缓存


强缓存:本地缓存

当浏览器二次请求服务器资源时,浏览器直接从本地缓存中读取并返回200,不会与服务器进行交互

协商缓存:浏览器根据HTTP响应头里面的内容,来采取对应的缓存方式

如果用户访问的资源在上次响应中携带了协商缓存相关的头,浏览器会携带相关字段并向服务端确认缓存的资源是否有效,如果服务端判断该资源有效,则返回304,携带相关缓存头但不返回资源内容,浏览器直接使用本地缓存。否则返回200,服务器返回新的资源内容。

3. 强缓存


强缓存相关HTTP headerExpiresCache-Control

Expires
  • ExpiresHTTP 1.0出现的响应头,它的值是GMT格式的时间字符串,如Expires: Sun Dec 24 2017 17:01:30 GMT。这个时间代表资源的过期失效时间,在这个时间之前,浏览器访问该资源时始终使用强缓存。
  • 缺点:Expires是个相对时间,如果服务端和客户端的时间相差较大,会导致缓存混乱。
Cache-Control
  • Cache-ControlHTTP 1.1出现的响应头,它可以用在请求头和响应头中,该指令是单向的,意味着在请求中设置的指令,在响应中可能没有。常用的值有max-ageno-cacheno-store
  • max-age是一个键值对,值为一个相对时间。例如Cache-Control: max-age=60代表该资源的有效时间为60s,在这60s内浏览器使用强缓存。如果该值与Last-Modified一起使用,该值优先级较高。
  • no-cache:==代表不使用强缓存,而是使用协商缓存。==代表浏览器在请求资源的时候必须先与服务器确认资源是否被更改,然后才能决定是否使用该资源。
  • no-store:==代表不适用缓存,每次都要从服务器重新获取。==所有内容都不会被缓存。
  • public:所有内容都会被缓存,客户端和代理服务器都可以缓存。
  • private:内容只能缓存在私有缓存中,即只有客户端可以缓存该资源,代理服务器不可以。

注意:如果同时存在expiresCache-Control,则Cache-Control优先级更高

4. 协商缓存


协商缓存相关头有:Last-Modified/If-Modified-SinceETag/If-None-Match。这两个相关头时成对出现的,前面的均为响应头,后面的为请求头。

Last-Modified/If-Modified-Since

Last-Modified代表的是资源的最后修改时间,是一个GMT格式的时间。服务器在返回资源时,如果写到Last-Modified,则浏览器在后续对该资源的访问的请求头里都会携带If-Modified-Since,值与服务器返回的Last-Modified值相同。服务端通过该值来判断浏览器请求的该资源是否有修改,如果有,则返回修改后的内容,且返回200,否则返回304,body中没有内容。

ETag/If-None-Match
  • ETag代表资源的内容,该值为资源的唯一标识符,HTTP没有规范该值如何生成,一般而言为该资源的散列值。当浏览器访问该资源时,服务端会根据资源计算出它的散列值(每一次都会重新计算),将计算出来的散列值与浏览器传来的值(If-None-Match)进行对比,如果相同则返回304,否则返回200且将新的资源的内容放入body中返回。
  • 用来标识一个资源。在具体实现中,ETag可以是资源的hash值,也可以是内部维护的版本号。总的来说,ETag是一个能够唯一标识一个资源的值且它能反映出资源内容的变化(ETag是资源的hash值时,若服务端的资源和浏览器端缓存的资源不一致,则ETag是不一致的,否则是相同的。当ETag是版本号时,当服务端的资源和浏览器端缓存的资源不一致时,ETag的取值也不一致,因为该资源对应的版本号是不同的
  • 当浏览器端第二次请求服务器时,利用If-None-Match来告知服务器,请求的这个资源在浏览器端有缓存,且它的ETag为***。如果服务器上的资源没有变化,即服务器上的该资源的ETag和第二次请求发送的If-None-Match值相同,则服务端会返回304响应。告知浏览器该资源没有改变,可以直接调用本地缓存。

5. Last-ModifiedETag


  • ETag主要是为了解决Last-Modified不能解决的问题。
  • 一些文件也许会周期性地改变,但是实际上它的内容不会改变,只会改变它在服务器端的最后修改时间,此时当浏览器端发来资源请求时,最后修改时间和服务器端的不一致。
  • 某些文件修改的非常频繁,比如在秒以下的时间内进行修改。而Last-Modified可检查到的粒度是秒级的,如果修改的特别频繁,是无法通过Last-Modified检测出来资源的变化的。
  • 某些服务器不能精确地得到文件的最后修改时间
  • ETagLast-Modified的补充,比Last-Modified更加严谨。但是ETag相对来说对性能会有影响。每次浏览器端将If-None-Match发送至服务端时,服务端都会对请求的资源进行散列值计算,然后与浏览器发来的值进行对比。每一次计算会对性能有一定的影响。

部分参考HTTP缓存

  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值