nginx Http2 Push 在 Vary 时失败:接受标头集

Posted

技术标签:

【中文标题】nginx Http2 Push 在 Vary 时失败:接受标头集【英文标题】:nginx Http2 Push fails when Vary: Accept header set 【发布时间】:2020-01-20 04:48:32 【问题描述】:

基本上,如果您在响应中设置标头 Vary: Accept,则使用 http2_push_preload 的 http2 推送不起作用,因为您正在使用 Accept 请求标头进行内容协商。我正在使用内容协商向支持它的客户端发送(http2 推送)webp 图片而不是 jpg。

HTTP/2 Push 适用于 .js、.css 文件和所有在同一个调用中,并在 Chrome DevTools 中显示“Push/Other”,但对于这种独特的情况(jpg 内容与 webp 协商)失败,并且只显示Chrome DevTools 中的“其他”(未推送)。

brotli 的内容协商、gzip 压缩都可以正常工作,并且可以使用 Vary: Accept-Encoding 正确推送,对于使用 Vary: Accept-Language 的语言也是如此。

仅变化:接受失败。 请帮助我正在放弃。

P.S:我正在通过 nginx 源 https://github.com/nginx/nginx/blob/master/src/http/v2/ngx_http_v2.c。执行 Crtl+F,您会发现只有“Accept-Encoding”和“Accept-Language”的案例,“Accept”没有。所以我认为nginx还不支持“接受”的情况??

P.P.S:我并没有过度推送,只是使用 http2 推送来获取英雄图像。

编辑:这是 nginx 网站上的错误票,供那些想要跟踪它的人使用: https://trac.nginx.org/nginx/ticket/1851 https://trac.nginx.org/nginx/ticket/1817

编辑 2:Nginx 团队回应说由于安全原因他们不会支持它(您可以在重复的错误帖子中找到响应),我认为这是由于来自不同来源(如 CDN)的推送?无论如何,我需要这个功能,所以剩下的唯一选择是:

    创建自定义补丁或包。

    使用其他一些支持它的服务器软件。

    如果请求来自支持 webp 的客户端,则在网站代码中手动实现将 .jpg 路径重写为 .jpg.webp 的功能。

(我不放弃:P)

【问题讨论】:

【参考方案1】:

我对此和Apache does the same 并不完全感到惊讶。如果您希望更改此设置,建议使用 nginx 提出一个错误,但如果他们没有优先考虑它也不会感到惊讶。

好像也是the browsers don't handle this situation very well either。

HTTP/2 推送充满了过度推送的机会,这就是一个例子。如果客户端不支持 WebP,您不应该推送,而且您通常不会通过此时掌握的信息知道这一点。例如,当您请求 html 时,Chrome 似乎会在 accept 标头中发送 webp,但 Firefox 不会。

预加载是一个更好、更安全的选项,它会考虑不同的标头和缓存状态。

【讨论】:

我已经浏览了您已经提到的链接。我没有过度推,只是发送英雄形象。在检查请求标头是否支持 webp 后,我正在进行内容协商。没有做任何假设。在 nginx 中,它是通过使用 map $http_accept $webp_suffix default ""; "~*webp" ".webp"; 并在服务器 区域中,通过执行 try_files $uri$webp_suffix 好的,所以只有在接受包含 webp 时才推送 - 就像 Chrome 在请求 HTML 文档时那样。在这种情况下,它不适用于 Firefix,因为它们不会在接受标头中发送 webp。但正如你所说,至少不要过度推动。答案是一样的——用 nginx 提出一个错误并希望他们修复它。 你提到的链接说 http/2 推送对于浏览器来说很难。但是我通过直接推送 .webp 图像变体对其进行了测试以检查问题不在浏览器端。我面临的问题是在 nginx 服务器端,如果它有 Accept: Vary,它不会推送文件。 是的,就像你说的 Chrome 支持它(以及所有基于 Chromium 的浏览器,如 Brave、Chromium 等),但我认为 Chrome 用户群非常高,所以它会有所作为。是的,它不适用于 Firefox。 是的,但即使这样有效,接下来您可能会在浏览器中看到问题。看起来 Chrome 通过外观修复了他们的错误,所以可能有效,但没有检查其余部分。不管答案是一样的 - 用 nginx 提出一个错误并希望他们修复它。

以上是关于nginx Http2 Push 在 Vary 时失败:接受标头集的主要内容,如果未能解决你的问题,请参考以下文章

Nginx + Koa 开启http/2 server push

发送 http2 请求时,recv() 在 nginx 错误日志中失败

网站提速:Http2 & server push 实践

php HTTP2 PUSH

如何处理 http2-push 和子目录?

Jetty HTTP2 服务器推送支持