如何从服务器端判断客户端是否支持 http/2

How to tell from server side if client supports http/2

我正在编写一个供网络用户使用的分析服务器。我要测试的参数之一是它们的浏览器支持。请告诉我是否可以获得休闲信息以及如何获得:

您最多只能通过他们的用户代理确定他们的浏览器,然后将其与某些浏览器和功能数据库进行交叉引用。

当然,用户代理可以说谎,但他们中的大多数人会适当地宣布自己。

这取决于所使用的网络服务器以及它提供的有关连接的详细信息。

例如Apache,提供了以下变量:https://httpd.apache.org/docs/2.4/mod/mod_http2.html#envvars

包括这些变量:

Variable Name:  Value Type:   Description:
HTTP2           flag          HTTP/2 is being used.
H2PUSH          flag          HTTP/2 Server Push is enabled for this connection and also supported by the client.
H2_PUSHED       string        empty or PUSHED for a request being pushed by the server.

因此您可以像这样使用 LogFormat 轻松地将其添加到您的日志文件中:

LogFormat "%h %l %u %t %{ms}T \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{SSL_PROTOCOL}x %{SSL_CIPHER}x %{Content-Encoding}o %{H2_PUSHED}e" combined

然后从日志文件中查看是否通过 HTTP/2.0 提供服务以及是否已推送。例如:

86.1.2.3 - - [11/Jul/2017:22:14:56 +0100] 2 "GET / HTTP/2.0" 200 1700 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 br
86.1.2.3 - - [11/Jul/2017:22:14:56 +0100] 3 "GET /assets/css/common.css HTTP/2.0" 200 5381 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 br PUSHED

这些变量也可用于 CGI 脚本等。请注意,只有在实际使用 HTTP/2 时才会设置这些变量。

并非所有 Web 服务器都像 Apache 一样容易公开此级别的详细信息,并且许多服务器不支持 HTTP/2 推送,因此可能无法检测到,因为它们本身不支持推送!

我不知道有任何 Web 浏览器从 HTTPS 客户端问候消息中提供这些详细信息(当 HTTP/2 将被协商时),因为大多数只提供 当前连接的详细信息,而不是每个协议都支持,而且只有在HTTPS会话建立之后。例如,这里给出了 Apache 的 HTTPS 变量:http://httpd.apache.org/docs/current/mod/mod_ssl.html#envvars

Web 服务器对 QUIC 的支持较少,因此不易检测到。

要从客户端实际检测到所有这些内容更加困难,因为据我所知,这些内容不会暴露给 JavaScript。最简单的选择是通过 HTTP/2 调用 CGI 脚本,其中 returns Web 服务器提供的那些值的结果。

请注意,推送的资源只会在需要时使用。如果需要但未推送,则无论如何都会获取它。所以你的js测试的想法,大概是检测是否正在使用推送的资源不会明确地说客户端是否支持推送,因为资源可能已被获取。