fangpsh's blog

Chrome,ERR_SPDY_PROTOCOL_ERROR 和无效的HTTP header

当你把网站迁移到性能更好的HTTP/2 协议时,可能会出现Chrome 没法加载页面的问题,取而代之是一个显示This site can’t be reached,以及错误信息为ERR_SPDY_PROTOCOL_ERROR 的页面。错误信息里面没有提到HTTP/2, 可能是因为 HTTP/2 是从SPDY 协议发展而来,所以错误信息还是老的SPDY。

chrome_err_spdy_protocol_error

出现ERR_SPDY_PROTOCOL_ERROR 可能是因为服务器发送了一个无效的HTTP header。Chrome 处理二进制的HTTP/2 协议时有一些严格,不会处理以空格代替破折号的header(例如用Referrer Policy 代替Referrer-Policy),也不会处理带着2个冒号的header(例如Content-Security-Policy:: ...),所以检查下你的header 是否准确。Firefox 会忽略这些无效的header,正常显示页面。

给出一个如何找到这些有问题的header 的方法。访问chrome://net-internals/#events(这链接没法点击,只能复制然后粘贴到地址栏再访问),在搜索框输入你的域名(我以example.com为例),然后在其他标签中打开出问题的网站。返回chrome://net-internals/#events ,选中Source Type 是HTTP2_SESSION 的行。

chrome-events-http2_session

在右边,可以看到HTTP/2 协议的详细信息,重点部分如下:

t=50413 [st=7]  HTTP2_SESSION_RECV_INVALID_HEADER
                --> header_name = "referrer policy"
                --> header_value = "same-origin"
t=50413 [st=7]  HTTP2_SESSION_SEND_RST_STREAM
               --> description = "Could not parse Spdy Control Frame Header."
               --> error_code = "1 (PROTOCOL_ERROR)"
               --> stream_id = 3

看到HTTP2_SESSION_RECV_INVALID_HEADER 那行了吗?无效的header 就在它下面,在这个问题中,无效的header 是referrer policy,用空格代替了破折号。HTTP/2 协议理的header 名称必须全小写,如果你发送一个Referrer-Policy的header,浏览器会视为referrer-policy。在这个问题中,被视为成无效的referrer policy

在你浏览器的chrome://net-internals/中,你能发现很多有趣的东西。这里有一些不会出现在开发者工具中的请求,例如浏览器扩展发出的请求。去试一试,说不定下次你debug 时能帮上忙。我在研究Opera browser “VPN” “VPN” in UR browser 就用过它。