Open FrankKai opened 3 years ago
ETag是HTTP response header。
标记资源version。 资源版本的唯一标识。 可以理解成一个唯一的hash。类似唯一标识或者版本标识。 类似uuid,primary key,package.json version,git commit hash,git tag等等。 目前接触过的唯一标识有uuid,数据库primary key等等。 目前接触过的版本号有package.json的version,commit hash等等。 目前接触过的tag有git的tag。
对资源标记版本的话,可以使得缓存的使用更加高效而且节省带宽。 因为如果content没有发生变化的话,server是没有必要重新发送一个完整的response到client的。
ETag可以阻止同时更新一个资源出现的覆盖问题。这个问题叫做“mid-air collisions”。
如果资源的URL发生了变化,必须生成一个新的ETag。 对比新旧资源的ETag可以判断出两个资源是不是相同的。
类似uuid,primary key,package.json version,git commit hash,git tag等等。 说得通俗易懂一些的话,与指纹类似,一些服务器可以通过ETag做到追踪。
可以。 ETag可以设置一个持久化的值,从而服务器可以永久追踪到,也算是一种数据持久化。
响应头。 ETag不是一个forbidden header name。
ETag: W/"<etag_value>" ETag: "<etag_value>"
'W/'(大小写敏感) 的意思是weak validator(弱验证)。 弱etag是很容易生成的,但是对于比较来说就不是很有用了。 强验证是最理想化的比较情况,但是很难高效率的生成。 同一资源的两种表现形式的弱ETag的值在语义上可能是等价的,但是并不是byte级相等。 weak etag在byte range requests使用时,阻止缓存;但是strong etag意味着range requests可以缓存。
content hash,last modification timestamp hash
etag: "5e7468cd-7de"
ETag与If-Match头一起作用时,可以检测到mid-air(空中)编辑冲突。 例如,在编辑MDN时,当前的wiki content被哈希化,之后在response的ETag中传入:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
当向wiki page存储内容时(比如发送数据),POST请求将在If-Match头中包含上ETag的值,去检查这个内容是不是fresh的:
If-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
如果hash没有匹配到,意味着文档在中间被编辑,然后抛出一个412状态码代表条件失败错误。
ETag头的另一个典型用处就是:缓存没有发生变化的资源。 如果用户再次访问了一个给定的URL(设置了ETag的资源),而且它是stale的(旧的:过于老导致不能使用),client会发送ETag的值在If-None-Match header上:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
服务端回对比cleint通过If-None-Match发送过来的ETag,并且与当前版本的资源对比。 如果两个值比对上了(说明资源没有变化),server会发送一个304 Not Modified状态码,并且没有body,会告诉client:”response的缓存版本当前是可用的。(fresh)“
dist目录中的vender.xxx.js,位于云存储上。
// req header if-none-match: "fafafaFkoHgQdfafafaC2xkHsKWPE8EvWnIDcq.gz" // res header etag: "fafafaFkoHgQdfafafaC2xkHsKWPE8EvWnIDcq.gz"
dist目录中的app.xxx.js,位于云存储上。
// req header Provisional headers are shown // res header etag: "FumFsXBIhM_vEqYsfLGotbfshnIdxRcVfs8.gz"
强验证。 关闭disable时:304。
弱验证。 开启disable时:200。
// req header 没有if-none-match cache-contorl: no-cache // res header etag: W/"sfFkYsIbsfafvg0crbkQpRWyzDWRPxFC9C"
参考资料:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
初识ETag
ETag是req header还是res header?
ETag是HTTP response header。
ETag的作用是什么?
标记资源version。 资源版本的唯一标识。 可以理解成一个唯一的hash。类似唯一标识或者版本标识。 类似uuid,primary key,package.json version,git commit hash,git tag等等。 目前接触过的唯一标识有uuid,数据库primary key等等。 目前接触过的版本号有package.json的version,commit hash等等。 目前接触过的tag有git的tag。
为什么要用对资源标记版本?
对资源标记版本的话,可以使得缓存的使用更加高效而且节省带宽。 因为如果content没有发生变化的话,server是没有必要重新发送一个完整的response到client的。
ETag还解决了什么问题?
ETag可以阻止同时更新一个资源出现的覆盖问题。这个问题叫做“mid-air collisions”。
如何生成一个ETag?
如果资源的URL发生了变化,必须生成一个新的ETag。 对比新旧资源的ETag可以判断出两个资源是不是相同的。
ETag和什么已知的知识点类似?
类似uuid,primary key,package.json version,git commit hash,git tag等等。 说得通俗易懂一些的话,与指纹类似,一些服务器可以通过ETag做到追踪。
ETag可以做持久化吗?
可以。 ETag可以设置一个持久化的值,从而服务器可以永久追踪到,也算是一种数据持久化。
ETag是响应头还是请求头?
响应头。 ETag不是一个forbidden header name。
ETag语法
ETag指令
W/ (Optional)
'W/'(大小写敏感) 的意思是weak validator(弱验证)。 弱etag是很容易生成的,但是对于比较来说就不是很有用了。 强验证是最理想化的比较情况,但是很难高效率的生成。 同一资源的两种表现形式的弱ETag的值在语义上可能是等价的,但是并不是byte级相等。 weak etag在byte range requests使用时,阻止缓存;但是strong etag意味着range requests可以缓存。
"" (核心)
content hash,last modification timestamp hash
或者直接一个版本号组成。例如mdn的etag由一个代表wiki文章内容的十六进制hash组成:etag: "5e7468cd-7de"
。避免mid-air相撞(ETag和If-Match)
ETag与If-Match头一起作用时,可以检测到mid-air(空中)编辑冲突。 例如,在编辑MDN时,当前的wiki content被哈希化,之后在response的ETag中传入:
当向wiki page存储内容时(比如发送数据),POST请求将在If-Match头中包含上ETag的值,去检查这个内容是不是fresh的:
如果hash没有匹配到,意味着文档在中间被编辑,然后抛出一个412状态码代表条件失败错误。
缓存未更改的资源
ETag头的另一个典型用处就是:缓存没有发生变化的资源。 如果用户再次访问了一个给定的URL(设置了ETag的资源),而且它是stale的(旧的:过于老导致不能使用),client会发送ETag的值在If-None-Match header上:
服务端回对比cleint通过If-None-Match发送过来的ETag,并且与当前版本的资源对比。 如果两个值比对上了(说明资源没有变化),server会发送一个304 Not Modified状态码,并且没有body,会告诉client:”response的缓存版本当前是可用的。(fresh)“
项目中的ETag分析
304
dist目录中的vender.xxx.js,位于云存储上。
200
dist目录中的app.xxx.js,位于云存储上。
disable cache与ETag
强验证。 关闭disable时:304。
弱验证。 开启disable时:200。
参考资料:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag