HTTP/2 规范表明,如果客户端取消它,在 PUSH_PROMISE 帧中标识的任何资源都不会被推送。
当浏览器检测到资源已经在缓存中时,它应该取消对该资源的推送。但是,我看不到浏览器如何检测到它。框架是否提供额外的信息,如 etag 或最后修改,以允许浏览器检测是否必须驱逐任何缓存条目或是否可以取消推送?
如果可能的话,可以节省一些带宽。但是,似乎服务器推送会损害任何客户端缓存优化。
HTTP/2 规范表明,如果客户端取消它,在 PUSH_PROMISE 帧中标识的任何资源都不会被推送。
当浏览器检测到资源已经在缓存中时,它应该取消对该资源的推送。但是,我看不到浏览器如何检测到它。框架是否提供额外的信息,如 etag 或最后修改,以允许浏览器检测是否必须驱逐任何缓存条目或是否可以取消推送?
如果可能的话,可以节省一些带宽。但是,似乎服务器推送会损害任何客户端缓存优化。
在 HTTP/2 中,服务器使用 PUSH_PROMISE 帧向客户端推送对资源的请求。
在从服务器到客户端时,这不是响应,而是请求,客户端为获取该资源而发出的请求。
当客户端收到 PUSH_PROMISE 时,它可以查看 URI,并找出该资源的缓存状态。浏览器通常对正常接收的资源和推送的资源使用不同的缓存。如果缓存仍然有效,客户端可以通过向服务器发送一个 RST_STREAM 帧来取消推送的流。
同时,服务器启动推送资源所需的一切。这将生成一个 HEADERS 响应帧,其中将包含典型的响应标头,例如 etag。当客户端接收到 HEADERS 响应帧时,它还有一次取消流的机会,尽管 - 当然 - DATA 帧可能正在传输中,可能是所有的。
节省带宽可能很有趣,但浪费一点带宽通常不是问题;从用户体验的角度来看,更重要的是延迟,而推送机制将其减少了相当多。
我认为推送机制不会损害任何客户端缓存优化;如果是这种情况,浏览器供应商将反对此功能,而他们中的大多数(如果不是全部)实施它,在用户体验和减少延迟方面取得了非常好的结果。
当然可以改进机制,例如通过让客户端和服务器就某些标头达成一致,该标头将提供有关被推送资源的更多信息,但到目前为止效果还不错。
[免责声明:我是 Jetty 提交者] 作为 Java 生态系统中第一个实现 SPDY 和 HTTP/2 推送的人(大约 3 年前),Jetty 项目当然对围绕 HTTP/2 推送的更多讨论和想法感兴趣。
简单而简短的回答:是的,如果浏览器在缓存中有此 URL,它将取消服务器推送。