Skip to main content

HTTP ETag 的强弱区别

ETag 用法

ETagHTTP 中常用的用于协商缓存的请求头,它代表一个资源的一个特定版本,当客户端首次请求该资源时,服务端在响应头中添加 ETag: "xxx" 。当客户端再次请求该资源时,可在请求头中添加 If-None-Match: "xxx" ,服务端收到该请求后,再次计算该资源的 ETag ,如果仍旧为 "xxx" ,则无需返回该资源的完整响应,只需返回 304 响应即可;如果不相同了,则返回新的资源的完整响应,并再次带上新的 ETag 。

ETag 强弱

根据 RFC 7232, section 2.1.,ETag 其实有两种:

ETag: W/"<etag_value>"
ETag: "<etag_value>"

第一种是弱的,第二种是正常的(也就是强的)。W/(区分大小写)开头表示使用弱校验。对于两个资源,强校验要求每个字节都相同才认为是同一个资源;而弱校验则把决定权交给开发者,根据需要区分的要素来生成相应的 ETag 。

为什么要区分强弱呢,因为大多数情况下,确保严格的字节级别的一致性是没有必要的。例如,如果我们开启了 HTTP 压缩,那么对于一个资源的响应,压缩前和压缩后的字节就是不一致的,但通常我们只关心压缩前的 ETag ,这时就需要使用弱校验的 ETag 。

在 Spring Web MVC 中实际应用

Spring Web MVC 中有一个 ShallowEtagHeaderFilter 可以校验请求的 ETag ,为响应生成 ETag 。它有一个 writeWeakETag 参数,控制 ETag 的强弱。

tip

当我们配置 server.compression.enabled=true 开启 HTTP 压缩后,必须设置 writeWeakETagtrue 使用弱校验 ETag 压缩才能生效。因为 ETag 是在压缩之前生成的,如果使用的是强校验 ETag ,Spring 就不会再进行压缩,保证 ETag 的一致性。