如何从服务器端判断客户端是不是支持 http/2
Posted
技术标签:
【中文标题】如何从服务器端判断客户端是不是支持 http/2【英文标题】:How to tell from server side if client supports http/2如何从服务器端判断客户端是否支持 http/2 【发布时间】:2017-12-15 22:34:21 【问题描述】:我正在编写一个供网络用户使用的分析服务器。我要测试的参数之一是它们的浏览器支持。请告诉我是否可以获得休闲信息以及如何获得:
测试客户端(用户浏览器)是否支持http/2 测试客户端(用户浏览器)是否支持http/2 pushes,一些如何检测服务器何时发送推送,客户端是否可以使用它,这可能是一些js测试,或者不是你告诉我的。 测试客户端(用户浏览器)是否支持QUIC,http/2的UDP版本【问题讨论】:
【参考方案1】:这取决于所使用的网络服务器以及它提供的有关连接的详细信息。
例如,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 %msT \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\" %SSL_PROTOCOLx %SSL_CIPHERx %Content-Encodingo %H2_PUSHEDe" 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 时才会设置这些变量。
并不是所有的网络服务器都像 Apache 那样容易地公开这种级别的细节,而且许多网络服务器不支持 HTTP/2 推送,因此可能无法检测到,因为它们自己不支持它!
我不知道有任何网络浏览器会从 HTTPS 客户端 hello 消息(协商 HTTP/2 时)中提供这些详细信息,因为大多数浏览器只提供当前连接的详细信息,而不是每个协议支持,并且仅在设置 HTTPS 会话之后。例如 Apache 的 HTTPS 变量在这里给出:http://httpd.apache.org/docs/current/mod/mod_ssl.html#envvars
网络服务器对 QUIC 的支持较少,因此不太容易检测到。
据我所知,从客户端实际检测所有这些内容更加困难,因为这些内容并未暴露给 javascript。最简单的选择是通过 HTTP/2 调用 CGI 脚本,该脚本返回 Web 服务器提供的这些值的结果。
请注意,只有在需要时才会使用推送的资源。如果需要并且没有推送,那么无论如何都会获取它。所以你关于js测试的想法,大概检测是否正在使用推送的资源并不能明确说明客户端是否支持推送,因为资源可能已被提取。
【讨论】:
我还不确定后端将使用什么服务器,所以我只想知道客户端发送到后端的内容,以便后端了解客户端支持的协议。 不管push,万一资源被push了,怎么从js测试你使用了push的资源,没有refetch呢 正如我所说,这完全取决于您选择的后端公开了哪些细节。正如我在答案中提到的,您无法区分已使用的推送资源和未推送的相同资源。除非您根据是否从后端知道是否支持推送来更改该资源的内容。 好的,了解推送 我查了一下,发现协议信息是和ssl握手一起协商的,客户端是启动的。因此,理论上,当 ssl 协商以客户端 hello 开始时,它应该已经发送有关它是否支持 http/2 或是否要使用 QUIC 的信息,这与您使用的服务器无关,也不管它是否支持http/2【参考方案2】:您能做的最好的事情就是通过他们的用户代理确定他们的浏览器,然后将其与一些浏览器和功能数据库进行交叉引用。
当然,用户代理可以撒谎,但他们中的大多数会适当地宣布自己。
【讨论】:
用户代理没有告诉你协议 那是正确的。如果您阅读了我实际所说的内容,这就是为什么我说您需要将用户代理与表示该用户代理的数据库交叉引用,它支持这些功能。浏览器中没有任何东西可以告诉它的协议。 服务器必须能够判断客户端是否支持 http/2,否则它如何知道与该客户端通信时使用什么协议。 你没看错,但是用户代理字符串可能是伪造的,或者当前连接不支持 HTTP/2 可能还有其他原因,例如未使用 HTTPS。以上是关于如何从服务器端判断客户端是不是支持 http/2的主要内容,如果未能解决你的问题,请参考以下文章