HTTP/2 服务器推送不工作,我做错了什么?
HTTP/2 Server Push not working, what am I doing wrong?
这是我的第一个问题,希望我做对了。
我正在使用带 HTTP/2(共享托管服务提供商)的 LiteSpeed 网络服务器,但我无法使用推送功能。我不太确定如何检查它是否有效,但至少据我所知它无法正常工作。
所以我查阅了大量指南(HTTP/2 Server Push Tutorial or A Comprehensive Guide To HTTP/2 Server Push 作为示例),他们都提到通过添加以下内容来更改 headers:
link: </my/theme/css/style.css>; rel=preload; as=style
我了解此代码告诉服务器预加载所述资源,在本例中为 style.css。但是,如果服务器支持 HTTP/2 推送,那么它应该自动推送资源(只要你不在它的末尾添加 nopush )。第二个 link 确实提到这对大多数服务器都是正确的,但不是所有服务器。
因此,考虑到这一点,我创建了一个简单的测试 PHP 页面,看看我是否可以让它正常工作。结果是这样的:
Chrome DevTools showing Headers tab with link preload
Network tab in DevTools showing the result
所以我看到的大多数指南都提到,推送资源的网络选项卡中的启动器会说 Push / Other(或类似的),而不仅仅是 Other,但正如您从我的结果中看到的那样,它只是说 Other。更不用说资源不会在同一个请求中加载,对我来说它只是一个简单的预加载。我还用 https://http2.pro/check 测试了我的网站,它说没有资源被推送。
这是用 Chrome 71.0.3578.98 测试的。
- 我是不是漏掉了什么重要的东西?会不会是我的服务器有问题?
- 另一个问题。在 headers 中为预加载和推送定义多个资源时,一些指南提到创建多个 link-elements,而其他人提到在单个 link-element 中用逗号分隔它们。这两个都正确吗,一个比另一个好吗?
感谢任何帮助或启发,谢谢!
因此,在 Chrome 中使用各种配置、浏览器版本和标志 enabled/disabled 进行一些测试以及使用网络事件查看器进行调查后,可能会出现一些问题。
如果 LiteSpeed Web 服务器启用了 QUIC,Chrome v71 似乎将请求显示为普通 GET 请求,并且不会指示它被推送,但是在网络事件查看器中查看 Chrome,它表明它确实被推送了(寻找QUIC_SESSION_PUSH_PROMISE_RECEIVED)。
现在,只有在浏览器中也启用了 QUIC 时才会出现这种情况,据我所知,目前在 Chrome v71 中默认情况下不是这样(它们禁用和启用东西不时) - 所以你要么必须在 Chrome 中设置一个标志来启用 QUIC,你会看到上述行为(你还应该在 web 下的 "Protocol" 中看到 http/2+quic/43
开发人员工具)。
如果 QUIC 未在浏览器或 Web 服务器上启用,您应该会看到正在推送的文件,并且 Chrome v71 会通过启动器 "Push / Other".[=15 指示这一点=]
现在,在 Chrome v73(金丝雀版本)中,"Initiator" 设置为 Other
,"Size" 应该是 (from memory cache)
,这表示正在推送的文件。
在GoogleChrome你可以去chrome://net-export/然后点击"Start Logging to Disk",然后刷新你的浏览器window您有需要推送的文件 - 停止测量,然后转到 https://netlog-viewer.appspot.com/ - 在此处导入 json 文件,然后转到 "QUIC",在列表中找到您的域名,然后点击 "Connection ID".
然后单击列表中的 "QUIC_SESSION",并搜索 QUIC_SESSION_PUSH_PROMISE_RECEIVED
- 如果有匹配项,您就知道文件已被推送。
要弄清楚它当前是否被推送需要一些挖掘,并且混淆主要与 Chrome 开发工具在协议和版本之间并不真正一致有关。
首先您需要了解您的基础架构是否使用Link headers 来激活推送。 Litespeed 文档在这里似乎不太好,但我们假设这就是您激活推送的方式。
接下来是检查您的服务器是否正在发送推送的请求。我发现 nghttp 是最好的工具,所以如果你也可以访问它,那么 运行 一个这样的命令来查看 HTTP/2 帧,如果 PUSH_PROMISE 帧被发送,表明正在推送样式 sheet:
nghttp -anv https://www.example.com
您还可以使用 Chrome 查看帧,虽然它们只是让这变得更加困难,但坚持先登录到磁盘,然后在查看器中打开。按照类似于@LucasRolff 的回答的说明进行操作,但对于 HTTP/2 或 here.
假设服务器正在推送资源,接下来您会知道为什么 Chrome 没有使用该推送的资源。最常见的原因是,如果您使用 self-signed TLS 证书来提供浏览器无法识别的 HTTPS。 Even if you click through the error and get a connection with a red padlock, Chrome will not use the cache for that connection, and so cannot use HTTP/2 push(这需要使用 HTTP/2 推送缓存)。如果是这种情况,nghttp 或 Chrome 事件日志输出应该显示。或者尝试使用 Firefox,如果单击无法识别的证书,它允许 HTTP/2 推送。
最后一个问题:
When defining multiple resources in the headers for preload and push, some guides mention creating multiple link-elements, while others mention comma separating them in a single link-element. Are both of these correct, is one better than the other?
两者都是正确的。 HTTP(无论是 HTTP/1.1 还是 HTTP/2)定义为:
header1: value1
header1: value2
还有这个:
header1: value1, value2
A recipient MAY combine multiple header fields with the same field
name into one "field-name: field-value" pair, without changing the
semantics of the message, by appending each subsequent field value to
the combined field value in order, separated by a comma.
这是我的第一个问题,希望我做对了。
我正在使用带 HTTP/2(共享托管服务提供商)的 LiteSpeed 网络服务器,但我无法使用推送功能。我不太确定如何检查它是否有效,但至少据我所知它无法正常工作。
所以我查阅了大量指南(HTTP/2 Server Push Tutorial or A Comprehensive Guide To HTTP/2 Server Push 作为示例),他们都提到通过添加以下内容来更改 headers:
link: </my/theme/css/style.css>; rel=preload; as=style
我了解此代码告诉服务器预加载所述资源,在本例中为 style.css。但是,如果服务器支持 HTTP/2 推送,那么它应该自动推送资源(只要你不在它的末尾添加 nopush )。第二个 link 确实提到这对大多数服务器都是正确的,但不是所有服务器。
因此,考虑到这一点,我创建了一个简单的测试 PHP 页面,看看我是否可以让它正常工作。结果是这样的:
Chrome DevTools showing Headers tab with link preload
Network tab in DevTools showing the result
所以我看到的大多数指南都提到,推送资源的网络选项卡中的启动器会说 Push / Other(或类似的),而不仅仅是 Other,但正如您从我的结果中看到的那样,它只是说 Other。更不用说资源不会在同一个请求中加载,对我来说它只是一个简单的预加载。我还用 https://http2.pro/check 测试了我的网站,它说没有资源被推送。
这是用 Chrome 71.0.3578.98 测试的。
- 我是不是漏掉了什么重要的东西?会不会是我的服务器有问题?
- 另一个问题。在 headers 中为预加载和推送定义多个资源时,一些指南提到创建多个 link-elements,而其他人提到在单个 link-element 中用逗号分隔它们。这两个都正确吗,一个比另一个好吗?
感谢任何帮助或启发,谢谢!
因此,在 Chrome 中使用各种配置、浏览器版本和标志 enabled/disabled 进行一些测试以及使用网络事件查看器进行调查后,可能会出现一些问题。
如果 LiteSpeed Web 服务器启用了 QUIC,Chrome v71 似乎将请求显示为普通 GET 请求,并且不会指示它被推送,但是在网络事件查看器中查看 Chrome,它表明它确实被推送了(寻找QUIC_SESSION_PUSH_PROMISE_RECEIVED)。
现在,只有在浏览器中也启用了 QUIC 时才会出现这种情况,据我所知,目前在 Chrome v71 中默认情况下不是这样(它们禁用和启用东西不时) - 所以你要么必须在 Chrome 中设置一个标志来启用 QUIC,你会看到上述行为(你还应该在 web 下的 "Protocol" 中看到 http/2+quic/43
开发人员工具)。
如果 QUIC 未在浏览器或 Web 服务器上启用,您应该会看到正在推送的文件,并且 Chrome v71 会通过启动器 "Push / Other".[=15 指示这一点=]
现在,在 Chrome v73(金丝雀版本)中,"Initiator" 设置为 Other
,"Size" 应该是 (from memory cache)
,这表示正在推送的文件。
在GoogleChrome你可以去chrome://net-export/然后点击"Start Logging to Disk",然后刷新你的浏览器window您有需要推送的文件 - 停止测量,然后转到 https://netlog-viewer.appspot.com/ - 在此处导入 json 文件,然后转到 "QUIC",在列表中找到您的域名,然后点击 "Connection ID".
然后单击列表中的 "QUIC_SESSION",并搜索 QUIC_SESSION_PUSH_PROMISE_RECEIVED
- 如果有匹配项,您就知道文件已被推送。
要弄清楚它当前是否被推送需要一些挖掘,并且混淆主要与 Chrome 开发工具在协议和版本之间并不真正一致有关。
首先您需要了解您的基础架构是否使用Link headers 来激活推送。 Litespeed 文档在这里似乎不太好,但我们假设这就是您激活推送的方式。
接下来是检查您的服务器是否正在发送推送的请求。我发现 nghttp 是最好的工具,所以如果你也可以访问它,那么 运行 一个这样的命令来查看 HTTP/2 帧,如果 PUSH_PROMISE 帧被发送,表明正在推送样式 sheet:
nghttp -anv https://www.example.com
您还可以使用 Chrome 查看帧,虽然它们只是让这变得更加困难,但坚持先登录到磁盘,然后在查看器中打开。按照类似于@LucasRolff 的回答的说明进行操作,但对于 HTTP/2 或 here.
假设服务器正在推送资源,接下来您会知道为什么 Chrome 没有使用该推送的资源。最常见的原因是,如果您使用 self-signed TLS 证书来提供浏览器无法识别的 HTTPS。 Even if you click through the error and get a connection with a red padlock, Chrome will not use the cache for that connection, and so cannot use HTTP/2 push(这需要使用 HTTP/2 推送缓存)。如果是这种情况,nghttp 或 Chrome 事件日志输出应该显示。或者尝试使用 Firefox,如果单击无法识别的证书,它允许 HTTP/2 推送。
最后一个问题:
When defining multiple resources in the headers for preload and push, some guides mention creating multiple link-elements, while others mention comma separating them in a single link-element. Are both of these correct, is one better than the other?
两者都是正确的。 HTTP(无论是 HTTP/1.1 还是 HTTP/2)定义为:
header1: value1
header1: value2
还有这个:
header1: value1, value2
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.