历史笔记

不能缓存的请求

  • 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的(需要传cookie的请求?)
  • 经过HTTPS安全加密的请求
    • IE 头部加入Cache-Control:max-age信息,能够对HTTPS的资源进行缓存(需验证)
    • firefox在头部加入Cache-Control:Public新能,能够对HTTPS的资源进行缓存(需验证)
  • POST请求无法被缓存
  • HTTP响应头中不包含Last-Modified、Etag,也不包含Cache-Control、Expires的请求无法被缓存

文件默认缓存机制

  • ETag:浏览器当前资源在服务器的唯一标识符
  • Last-Modified:资源最后的修改时间。服务器将资源传递给客户端时,会将资源最后更改的时间传递给浏览器
  • 是否过期由Expires或Cache-Control决定

——————————————————————————————————————————

HTTP头部设置

是否过期

  • Pragma: no-cache
    • 是一个在 HTTP/1.0 中规定的通用首部,这个首部的效果依赖于不同的实现,所以在“请求-响应”链中可能会有不同的效果。
    • 它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器,那时候 HTTP/1.1 协议中的 Cache-Control 还没有出来。建议只在需要兼容 HTTP/1.0 客户端的场合下应用 Pragma 首部。
    • 假如 Cache-Control 不存在的话,它的行为与 Cache-Control: no-cache 一致。强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行验证。
  • Expires: Mon, 15 Aug 2016 03:56:47 GMT
    • 响应头,定义缓存时间。告诉浏览器资源缓存过期时间,如果还没过该时间点则不发请求
    • 该字段所定义的缓存时间是相对服务器上的时间而言的,如果客户端上的时间跟服务器上的时间不一致(特别是用户修改了自己电脑的系统时间),那缓存时间可能就没啥意义了。
    • 如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。
  • Date: Wed, 21 Oct 2015 07:28:00 GMT 一个通用首部,其中包含了报文创建的日期和时间。
  • Cache-Control: 被用于在http 请求和响应中,通过指定指令来实现缓存机制。
    • 指令不区分大小写,并且具有可选参数,可以用令牌或者带引号的字符串语法。多个指令以逗号分隔。
    • 请求可以包含的指令
      • max-stale[=<seconds>] 表明客户端愿意接收一个已经过期的资源。 可选的设置一个时间(单位秒),表示响应不能超过的过时时间。
      • min-fresh=<seconds> 表示客户端希望在指定的时间内获取最新的响应。
      • no-store
      • max-age=<seconds>
      • no-transform
      • no-cache 强制高速缓存将请求提交给原始服务器进行验证。
      • only-if-cached 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝(代理服务器?)
    • 响应可以包含的指令
      • max-age=<seconds> 设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。
      • must-revalidate 缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。
      • no-cache 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给服务器,拉取资源,但不是“不缓存”。
      • no-store 缓存不应存储有关客户端请求或服务器响应的任何内容
      • private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)
      • public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
      • proxy-revalidate 与 must-revalidate 作用相同,但它仅适用于共享缓存(例如代理)
      • s-maxage=<seconds> 覆盖 max-age 或者 Expires 头,但是仅适用于共享缓存(比如各个代理)(代理服务器设置的max-age?)
      • no-transform 不得对资源进行转换或转变。Content-Encoding, Content-Range, Content-Type等HTTP头不能由代理修改。例如,非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。 no-transform指令不允许这样做。
    • 常用但不属于标准的指令包括immutable、stale-while-revalidate=<seconds>、stale-if-error=<seconds>
Cache-Control: no-cache, no-store, must-revalidate

标志和修改时间

  • ETag:"fd56273325a2114818df4f29a628226d" 或 ETag: W/"0815"
    • HTTP响应头是资源的特定版本的标识符,根据文件内容生成,文件内容不变则不变
    • 如果内容没有改变,Web服务器不需要发送完整的响应。
    • 如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。POST请求将包含有ETag值的If-Match头来检查是否为最新版本。
    • 比较etags能快速确定此资源是否变化,可以用以解决Last-Modified只能精确到秒的问题,请求高速变动的资源。但也可能被跟踪服务器永久存留。
    • ETag: W/"<etag_value>" 'W/'(大小写敏感) 表示使用弱验证器。 弱验证器很容易生成,但不利于比较。 强验证器是比较的理想选择,但很难有效地生成。 相同资源的两个弱Etag值可能语义等同,但不是每个字节都相同。
    • 如果用户再次访问给定的URL(设有ETag字段),显示资源过期了且不可用,客户端就发送值为ETag的If-None-Match header字段
  • Last-Modified:Mon, 15 Aug 2016 03:56:47 GMT(GMT 国际标准时间,0时区时间)
    • 一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。
    • 服务器将资源传递给客户端时,会将资源最后更改的时间以“Last-Modified: GMT”的形式加在实体首部上一起返回给客户端
    • 精确度比 ETag 要低,所以这是一个备用机制
    • 只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
    • 分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败

协商缓存(请求头)

  • If-None-Match: "fd56273325a2114818df4f29a628226d" (资源如果过期,通过 Etag 判断缓存是否过期并且避免空中冲突)
    • 一个条件式请求首部,Etag的值。资源过期时发送
    • 对于 GET 和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的相匹配的时候,服务器端会才返回所请求的资源,响应码为 200 。
    • 对于 GET 和 HEAD 方法来说,当验证失败的时候(有相同的Etag),服务器端必须返回响应码 304 (Not Modified,未改变)。
    • 服务器端在生成状态码为 304 的响应的时候,必须同时生成以下会存在于对应的 200 响应中的首部:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary 。
    • 对于能够引发服务器状态改变的方法,则返回 412 (Precondition Failed,前置条件失败)。该请求传递 If-None-Match 是为了避免空中冲突(要修改的资源是否已经被修改过),当出现冲突时返回412
    • 当与 If-Modified-Since 一同使用的时候,If-None-Match 优先级更高(假如服务器支持的话)。
    • 星号是一个特殊值,可以代表任意资源。它只用在进行资源上传时,通常是采用 PUT 方法,来检测拥有相同识别ID的资源是否已经上传过了。(应该是告诉服务器这个资源需要校重,当服务器生成的 Etag 相同时就认为这个请求被重复提交不予通过)
If-None-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"

If-None-Match: W/"67ab43", "54ed21", "7892dd"

If-None-Match: *
  • If-Modified-Since:Mon, 15 Aug 2016 03:56:47 GMT (资源如果过期并且没有 Etag,通过更新时间判断缓存是否过期)
    • 一个条件式请求首部,其值为上次响应头的Last-Modified值
    • 服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 。(资源内容写在响应消息包体内,并更新Last-Modified的值)
    • 如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 响应,而在 Last-Modified 首部中会带有上次修改时间。
    • If-Modified-Since 只可以用在 GET 或 HEAD 请求中。
    • 当与 If-None-Match 一同出现时,它(If-Modified-Since)会被忽略掉,除非服务器不支持 If-None-Match。

断点续传

  • If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d" 或 If-Match: W/"67ab43", "54ed21", "7892dd" 或 If-Match: *(资源没有过期,通过 Etag 判避免空中冲突)
    • 在请求方法为 GET 和 HEAD 的情况下,服务器仅在请求的资源满足此首部列出的 ETag 之一时才会返回资源。
    • 对于 PUT 或其他非安全方法来说,只有在满足条件的情况下才可以将资源上传。
    • 对于 GET 和 HEAD 方法,搭配 Range首部使用,如果 ETag 无法匹配,那么需要返回 416(范围请求无法满足)
    • 对于其他方法来说,尤其是 PUT, 如果请求的条件不满足,那么需要返回 412 (Precondition Failed,先决条件失败) 响应
  • If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT 请求头(通过更新时间避免空中冲突)
    • 只有当资源在指定的时间之后没有进行过修改的情况下,服务器才会返回请求的资源,或是接受 POST 或其他 non-safe 方法的请求。
      • non-safe:不会修改资源的请求方式,例如 get、head
    • 如果所请求的资源在指定的时间之后发生了修改,那么会返回 412 (Precondition Failed) 错误。
    • 与含有 If-Range 消息头的范围请求搭配使用,用来确保新的请求片段来自于未经修改的文档。
  • If-Range: Wed, 21 Oct 2015 07:28:00 GMT
    • If-Range 头字段通常用于断点续传的下载过程中,用来自从上次中断后,确保下载的资源没有发生改变。
    • 当字段值中的条件得到满足时,Range 头字段才会起作用,同时服务器回复206 部分内容状态码,以及Range 头字段请求的相应部分;(续传成功)
    • 如果字段值中的条件没有得到满足,服务器将会返回 200 OK 状态码,并返回完整的请求资源。(续传不成功,重头下载)
    • 字段值中既可以用 Last-Modified 时间值用作验证,也可以用ETag标记作为验证,但不能将两者同时使用。

代理服务器相关头部

  • Age: 24 消息头(响应头)里包含消息对象在缓存代理中存贮的时长,以秒为单位。.
    • Age消息头的值通常接近于0。表示此消息对象刚刚从原始服务器获取不久;

相关头部和响应码

  • Content-Location: /index.html (响应头-资源协商后路径)
    • 首部指定的是要返回的数据的地址选项。最主要的用途是用来指定要访问的资源经过内容协商后的结果的URL。
    • Location 与 Content-Location是不同的,前者(Location )指定的是一个重定向请求的目的地址(或者新创建的文件的URL),而后者( Content-Location) 指向的是可供访问的资源的直接地址,不需要进行进一步的内容协商。
  • Location: /index.html(响应头-重定向)
    • 指定的是需要将页面重新定向至的地址。一般在响应码为3xx的响应中才会有意义。
    • 获取Location指向的新页面所采用的方法与初始请求使用的方法以及重定向的类型相关:
      • 303 始终引致请求使用 GET 方法
      • 307 和 308 则不转变初始请求中的所使用的方法
      • 301 和 302在大多数情况下不会转变初始请求中的方法,不过一些比较早的用户代理可能会引发方法的变更
    • 状态码为 201 的消息也会带有Location首部。它指向的是新创建的资源的地址。
  • Vary: User-Agent (响应头-下一个请求头约束)
    • 响应头部,它决定了对于未来的一个请求头,应该用一个缓存的回复还是向源服务器请求一个新的回复。(代理服务器?)
    • 服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers).(同一个资源根据头部信息返回不同的数据,适用于不同的设备)
    • 在响应状态码为 304 Not Modified 的响应中,也要设置 Vary 首部,而且要与相应的 200 OK 响应设置得一模一样。
    • 例如你提供给移动端的内容是不同的,可用防止你客户端误使用了用于桌面端的缓存。 并可帮助Google和其他搜索引擎来发现你的移动端版本的页面。Vary: User-Agent
  • User-Agent(请求头-系统、浏览器类型)
  • Content-Type: text/html; charset=utf-8 或 Content-Type: multipart/form-data; boundary=something (响应主体类型)
    • 用于指示资源的MIME类型 media type 。
    • 浏览器会在某些情况下进行MIME查找,并不一定遵循此标题的值; 为了防止这种行为,可以将标题 X-Content-Type-Options 设置为 nosniff。
    • 在请求中 (如POST 或 PUT),客户端告诉服务器实际发送的数据类型。
    • 指令
      • text/html:media-type 资源或数据的 MIME type
      • charset=utf-8:charset 字符编码标准。
      • boundary 对于多部分实体,boundary 是必需的,其包括来自一组字符的1到70个字符,已知通过电子邮件网关是非常健壮的,而不是以空白结尾。它用于封装消息的多个部分的边界。???
  • X-Content-Type-Options: nosniff(响应头-响应主体格式解析限定)
    • 响应首部相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改。
    • nosniff 只应用于 "script" 和 "style" 两种类型。事实证明,将其应用于图片类型的文件会导致与现有的站点冲突。
  • Content-Encoding: gzip (响应主体压缩类型)
    • 当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。
    • 这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。
    • 对于特定类型的文件来说,比如jpeg图片文件,已经是进行过压缩的了。有时候再次进行额外的压缩无助于负载体积的减小,反而有可能会使其增大。
    • 可用的指令包括 gzip、compress、deflate、identity(未压缩)、br
  • Range: bytes=200-1000, 2000-6576, 19000- (请求资源的字节区间)
    • 一个请求首部,告知服务器返回文件的哪一部分
    • 可以一次性请求多个部分,服务器会以 multipart 文件的形式将其返回
    • 如果服务器返回的是范围响应,需要使用 206 Partial Content 状态码。
    • 假如所请求的范围不合法,那么服务器会返回 416 Range Not Satisfiable 状态码
    • 服务器允许忽略 Range 首部,从而返回整个文件,状态码用 200 。
    • 指令:
      • unit 范围所采用的单位,通常是字节(bytes)。
      • range-start 一个整数,表示在特定单位下,范围的起始值。
      • range-end 一个整数,表示在特定单位下,范围的结束值。这个值是可选的,如果不存在,表示此范围一直延伸到文档结束
  • Content-Range: bytes 200-1000/67589 (响应数据的字节区间)
    • 响应首部 Content-Range 显示的是一个数据片段在整个文件中的位置。
    • 数据区间所采用的单位。通常是字节(byte)。
    • 一个整数,表示在给定单位下,区间的起始值
    • 一个整数,表示在给定单位下,区间的结束值。
    • / 整个文件的大小(如果大小未知则用"*"表示)。
  • 206
    • 表示请求已成功,并且主体包含所请求的数据区间,该数据区间是在请求的 Range 首部指定的。
    • 如果只包含一个数据区间,那么整个响应的 Content-Type 首部的值为所请求的文件的类型,同时包含 Content-Range 首部。
    • 如果包含多个数据区间,那么整个响应的 Content-Type 首部的值为 multipart/byteranges ,其中一个片段对应一个数据区间,每个片段分别提供 Content-Range 和 Content-Type 描述信息。
  • 304
    • 说明无需再次传输请求的内容,也就是说可以使用缓存的内容。
    • 很多浏览器的 开发者工具 会发出额外的请求,以达到 304 的目的,这样可以把资源以本地缓存的形式展现给开发者。
  • 412
    • 先决条件失败,请求的操作——通常是上传或修改文件——无法执行,从而返回该错误状态码。
    • 通常发生于采用除 GET 和 HEAD 之外的方法进行条件请求时,由首部字段 If-Unmodified-Since 或 If-None-Match 规定的先决条件不成立的情况下。
  • 416
    • 服务器无法处理所请求的数据区间
    • 最常见的情况是所请求的数据区间不在文件范围之内,也就是说,Range 首部的值,虽然从语法上来说是没问题的,但是从语义上来说却没有意义。
    • 416 响应报文包含一个 Content-Range 首部,提示无法满足的数据区间(用星号 * 表示),后面紧跟着一个“/”,再后面是当前资源的长度。例如:Content-Range: */12777
    • 遇到这一错误状态码时,浏览器一般有两种策略:要么终止操作(例如,一项中断的下载操作被认为是不可恢复的),要么再次请求整个文件。

——————————————————————————————————————————

Meta标签

  • 这可能是过往 IE 版本的兼容方案,在 MDN 的 meta 标签,没有关于浏览器缓存的限制方法
// 仅有IE才能识别这段meta标签含义,其它主流浏览器仅识别“Cache-Control: no-store”的meta标签。
// 这两个属性在MDN中没有记载,都和http请求头部相关。

// 在IE中识别到该meta标签含义,并不一定会在请求字段加上Pragma,但的确会让当前页面每次都发新请求(仅限页面,页面上的资源则不受影响)。
// no-cache 告诉浏览器忽略资源的缓存副本,每次访问都需要去服务器拉取
<meta http-equiv="Pragma" content="no-cache">  

// no-cache 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给服务器,拉取资源,但不是“不缓存”。(Ctrl+F5会重置Cache-Control=no-cache)
// no-store 强制缓存在任何情况下都不要保留任何副本
// must-revalidate 缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
原文地址:https://www.cnblogs.com/qq3279338858/p/10393881.html