更新的问题
我的应用程序如何利用 etags,引入流/分块编码是否会带来任何复杂性?
原始问题
使用 进行 HTTP 流式传输时Transfer-Encoding: chunked
,Content-Length
无法发送,因为它通常是未知的。
据我了解,当浏览器利用 etag 时,他们需要知道Content-Length
. 如果提供了 etag 但未提供Content-Length
,浏览器将永远不会发送If-None-Match
.
有没有解决的办法?
我的应用程序如何利用 etags,引入流/分块编码是否会带来任何复杂性?
使用 进行 HTTP 流式传输时Transfer-Encoding: chunked
,Content-Length
无法发送,因为它通常是未知的。
据我了解,当浏览器利用 etag 时,他们需要知道Content-Length
. 如果提供了 etag 但未提供Content-Length
,浏览器将永远不会发送If-None-Match
.
有没有解决的办法?
Etags 是用于版本页面的 http 标头,如果页面没有更改,则允许客户端重新使用以前缓存的页面副本。
基本思想是客户端进入一个页面并向拥有该页面的服务器发送一个http请求。然后,服务器呈现页面并将响应与包含某些值的 etag 一起返回给客户端。除了显示页面之外,客户端还会将该页面的副本连同 etag 一起归档到其本地缓存中。下次客户端访问该页面时,客户端将向网络服务器发出请求,但将 etag 包含在If-None-Match
标头中。这样的请求称为条件 GET。客户说,“我想要这个页面,但是我已经有一个带有这个 etag 值的页面的缓存版本,所以如果你认为我的缓存版本是最新的,请告诉我,我会显示我的缓存副本给用户”。
etag 值没有任何语义要求。它应该用于存储允许您确定客户端副本是否是最新的值。
最简单的方法是计算响应的哈希值,如果哈希值与请求标头中的 etag 值匹配,则客户端已经拥有相同的副本,您可以304 No content
在响应中返回 a 并返回一个空正文。这比再次返回整个页面要快得多。
虽然计算哈希是确定缓存是否仍然良好的一种简单而安全的方法,但存在更智能的技术可以让您减少 Web 服务器上的负载。考虑一个在网上商店中显示产品的页面。updated_at
您可以只使用产品的属性,而不是使用产品描述呈现页面,然后计算和比较哈希值。这意味着您在应用程序中做的第一件事是检查 etag 并从数据库中获取产品以比较updated_at
属性。如果匹配,您假设产品的详细信息没有更改,您可以完成请求处理而无需进一步执行任何操作,然后返回304 No content
响应。
但是,您应该小心这种优化,因为页面上可能有其他内容可能会变得过时,而不会影响updated_at
数据库中产品的属性。这可能是带有最新消息的侧边栏,或者更糟糕的是,页面的个性化部分,例如列出先前添加的产品的购物车。
分块编码只是一种以多个块传输响应的技术,因此接收客户端可以更快地开始呈现页面,而服务器仍在处理剩余的块。它与缓存没有任何关系。但是,如果您想使用响应的散列值作为 etag,这显然是不可能的,因为在您知道完整响应之前发送标头,这是计算散列所必需的。