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