【问题标题】:What's the net::ERR_HTTP2_PROTOCOL_ERROR about?net::ERR_HTTP2_PROTOCOL_ERROR 是关于什么的?
【发布时间】:2020-02-01 12:50:38
【问题描述】:

我目前正在开发一个网站,该网站在 Google Chrome 上触发了 net::ERR_HTTP2_PROTOCOL_ERROR 200 错误。我不确定究竟是什么引发了这个错误,我只是注意到它只有在以 HTTPS 访问网站时才会弹出。我不能 100% 确定它是相关的,但看起来它会阻止 JavaScript 正确执行。

例如,会发生以下情况:

  1. 我正在使用 HTTPS 访问网站

  2. 我通过 https://publish.twitter.com 集成的 Twitter 提要根本没有加载

  3. 我可以在控制台中注意到 ERR_HTTP2_PROTOCOL_ERROR

  4. 如果我删除加载 Twitter 提要的代码,错误仍然存​​在

  5. 如果我使用 HTTP 访问该网站,则会出现 Twitter 提要并且错误消失

Google Chrome 是唯一触发错误的网络浏览器:它在 Edge 和 Firefox 上都能正常运行。 (注意:我用 Safari 试过,我也有类似的kcferrordomaincfnetwork 303 错误)

我想知道它是否与服务器返回的标头有关,因为错误中提到了“200”,并且 404 / 500 页面没有触发任何内容。

问题是根本没有记录错误。谷歌搜索给我的结果很少。此外,我注意到它出现在最近的 Google Chrome 版本中;该错误不会在 v.64.X 上弹出,但在 v.75+ 上会出现(无论操作系统如何;我正在使用 Mac 版)。


可能与Website OK on Firefox but not on Safari (kCFErrorDomainCFNetwork error 303) neither Chrome (net::ERR_SPDY_PROTOCOL_ERROR)有关


进一步调查的结果如下:

  • 如果服务器返回 404 而不是 2XX,则不会在完全相同的页面上弹出错误
  • 使用 HTTPS 证书在本地不会弹出错误
  • 在使用不同证书的不同服务器(两者都是 OVH)上弹出错误
  • 无论使用什么 PHP 版本,从 5.6 到 7.3 都会弹出错误(使用的框架:Cakephp 2.10)

根据要求,以下是失败资源的返回标头,即整个网页。即使在每个具有 HTTP 标头 200 的页面上触发错误,这些页面总是在客户端的浏览器上加载,但有时会丢失一个元素(在我的示例中,外部 Twitter 提要)。网络选项卡上的所有其他资产都有成功返回,但整个文档本身除外。

Google Chrome 标头(有错误):

Firefox 标头(无错误):

控制台中的curl --head --http2 请求返回以下成功:

HTTP/2 200 
date: Fri, 04 Oct 2019 08:04:51 GMT
content-type: text/html; charset=UTF-8
content-length: 127089
set-cookie: SERVERID31396=2341116; path=/; max-age=900
server: Apache
x-powered-by: PHP/7.2
set-cookie: xxxxx=0919c5563fc87d601ab99e2f85d4217d; expires=Fri, 04-Oct-2019 12:04:51 GMT; Max-Age=14400; path=/; secure; HttpOnly
vary: Accept-Encoding

尝试更深入地使用 chrome://net-export/ 和 https://netlog-viewer.appspot.com 工具告诉我请求以 RST_STREAM 结束:

t=123354 [st=5170]    HTTP2_SESSION_RECV_RST_STREAM
                      --> error_code = "2 (INTERNAL_ERROR)"
                      --> stream_id = 1

对于我在this other post 中读到的内容,“在 HTTP/2 中,如果客户端想要中止请求,它会发送一个 RST_STREAM。当服务器接收到一个 RST_STREAM 时,它将停止发送 DATA 帧到客户端,从而停止响应(或下载)。该连接仍可用于其他请求,并且与已中止的请求/响应并发的请求/响应可能会继续进行。 [...] 有可能当 RST_STREAM 从客户端传输到服务器时,请求的全部内容都在传输中并将到达客户端,客户端将丢弃它。但是,对于较大的响应内容,发送一个 RST_STREAM 可能有很大的机会在整个响应内容发送之前到达服务器,因此会节省带宽。"

所描述的行为与我观察到的行为相同。但这意味着浏览器是罪魁祸首,然后我不明白为什么它会发生在两个相同的页面上,一个具有 200 标题,另一个具有 404(如果我禁用 JS,也是如此)。

【问题讨论】:

  • 明明来过这里,也只有客户端相关的答案,不能解决。
  • 非chrome浏览器是否出现错误?如果不是,怎么不是客户端(特别是 Chrum 浏览器)问题?
  • 可能是格式错误的 HTTP 响应标头。整个网站没有加载吗?还是只有一项或多项资产?您能否编辑问题以包含在使用 HTTP/2 时未加载的资产的 http 响应中显示的 HTTP 响应标头?还有适用于 Edge/Firefox 的地方吗?
  • 看不到任何问题,因此怀疑这不是主要要求。也忽略饼干的东西 - 不是那样的。试试这个,看看你能不能弄清楚:michalspacek.com/…

标签: php wordpress google-chrome curl http2


【解决方案1】:

我没有弄清楚到底发生了什么,但我找到了解决方案。

OVH 的 CDN 功能 是罪魁祸首。我已将它安装在我的主机服务上,但因为我不需要它而对我的域禁用。

不知何故,当我启用它时,一切正常。

我认为它迫使 Apache 使用 HTTP2 协议,但我不明白的是,我的每个标头中确实都提到了 HTTP2,我认为这意味着服务器正在使用正确的协议进行响应。

因此,针对我的特殊情况的解决方案是在所有相关域上启用 CDN 选项。

如果有人更了解这里可能发生的事情,请随时分享解释。

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,我在其中一个 HTTP GET 请求上收到 ERR_HTTP2_PROTOCOL_ERROR。

    我注意到 Chrome 更新处于等待状态,所以我将 Chrome 浏览器更新到最新版本,下次重新启动浏览器时错误消失了。

    【讨论】:

    • 我也是,这个答案是唯一有意义的,因为它不是特定于单个网站或我拥有的网站,而只是任意网站。
    【解决方案3】:

    我在发布大于 1MB 的文件时遇到了同样的问题(asp,c# - HttpPostedFileBase)(即使应用程序对文件大小没有任何限制),对我来说简化模型类很有帮助。如果您遇到此问题,请尝试删除模型的某些部分,看看它是否会有所帮助。听起来很奇怪,但对我有用。

    【讨论】:

      【解决方案4】:

      几个星期以来,我也对这个“错误”感到恼火:

      net :: ERR_HTTP2_PROTOCOL_ERROR 200
      

      在我的例子中,它发生在 PHP 生成的图像上。

      它在header() 级别,尤其是在这个级别:

      header ('Content-Length:'. Filesize($cache_file));
      

      它显然没有返回确切的大小,所以我删除了它,现在一切正常。

      所以 Chrome 会检查通过 headers 传输的数据的准确性,如果不对应,则失败。

      编辑

      我发现content-length 通过filesize 计算错误的原因:GZIP 压缩在 PHP 文件上处于活动状态,因此排除有问题的文件将解决问题。把这段代码放在.htaccess:

      SetEnvIfNoCase Request_URI ^ / thumb.php no-gzip -vary
      

      它有效,我们保留标题Content-length

      【讨论】:

      • 太好了,你救了我!!!但我仍然不明白真正的问题,在我的情况下,错误只发生在 https 而不是 http。
      • 你好@Nico,是的,我认为这很正常,公布的大小与浏览器(Chrome)下载的文件的大小之间的验证应该只在https协议中进行。很高兴这个解决方案能帮到您!
      • 不知何故我设法使用“内容长度”而不是“内容长度”。删除空间后,它起作用了。谢谢。
      • 我遇到了 Livewire 没有在共享主机中加载其 JS 的问题,而我可以在浏览器中打开相同的路径而没有问题。我不明白为什么这有效,但确实有效。黑魔法。谢谢。
      • > 它显然没有返回确切的大小,所以我删除了它,现在一切正常。这个修复对我有用。在 C# 中,我这样做了:``` result.Content.Headers.ContentLength = null; ```
      【解决方案5】:

      我遇到这种情况是因为 http2 服务器在向 Chrome 发送大响应时关闭了连接

      为什么? 因为它只是http2服务器的一个设置,命名为WriteTimeout

      【讨论】:

      • 是的,这解决了我的 Go 服务器的问题。谢谢!
      【解决方案6】:

      当我有一个将 node-js 应用程序暴露给外部世界的 Nginx 服务器时,我遇到了这个问题。 Nginx 使用gzip 压缩文件(css、js、...),并且使用 Chrome 看起来一样。

      当我们发现node-js服务器也是用gzip压缩内容时问题解决了。在某种程度上,这种双重压缩导致了这个问题。取消 node-js 压缩解决了这个问题。

      【讨论】:

      • 有趣的是,已经有好几个人回答了这个帖子,而且每次问题的根源都不同。我认为这个错误确实很令人困惑。
      【解决方案7】:

      上周我一直遇到这个问题,因为我一直在尝试通过 AJAX 向我的 PHP 服务器发送 DELETE 请求。我最近升级了我的托管计划,现在我的主机上有一个 SSL 证书,用于存储 PHP 和 JS 文件。自从添加 SSL 证书后,我不再遇到此问题。希望这有助于解决这个奇怪的错误。

      【讨论】:

        【解决方案8】:

        在我的情况下,网络服务器上没有剩余磁盘空间。

        【讨论】:

        • 有趣,对我来说也是一样,前端网络服务器磁盘已满。似乎 nginx 没有捕捉到这种情况,因为日志中没有什么值得注意的。
        • 只是向任何想知道为什么这会导致协议错误的人解释一下,因为我们也得到了类似的东西,并且想知道发生了什么。问题是,当磁盘上没有剩余磁盘空间时,一些网络服务器(肯定是 nginx,但也可能是 apache)无法发送整个响应,并且通常只是在响应的第一个“chuck”发送后丢弃请求。这会导致内容长度标头与接收到的实际内容不匹配。这(如@Xtendo 所述)可能导致 http2 协议错误。
        • 谢谢你。我有同样的问题(nginx)。我们没有空间不足,但它已满 90%。此问题仅发生在具有大量内容的页面上(表格中包含 600 多行内容的大型报告)。在 AWS 中增加磁盘大小立即解决了这个问题。
        【解决方案9】:

        我也遇到了这个错误,我相信这背后可能有多种原因。我的是,ARR 正在超时。

        在我的情况下,浏览器正在向我设置了重定向规则的反向代理站点发出请求,并且该代理站点最终请求实际站点。现在对于大量数据,它需要超过 2 分 5 秒,并且我的服务器的应用程序请求路由超时设置为 2 分钟。我通过以下步骤增加 ARR 超时来解决此问题: 1. 进入 IIS 2.点击服务器名称 3.点击中间窗格中的Application Request Routing Cache 4.单击右窗格中的服务器代理设置 5.增加超时 6. 点击应用

        【讨论】:

        • 也为我修复了它,谢谢@Ankit。
        【解决方案10】:

        在我们的例子中,原因是标题无效。 如编辑 4 所述:

        • 记录日志
        • 在查看器中选择事件
        • 选择HTTP2_SESSION

        寻找类似的东西:

        HTTP2_SESSION_RECV_INVALID_HEADER

        --> error = "标题名称中的字符无效。"

        --> header_name = "charset=utf-8"

        【讨论】:

          【解决方案11】:

          我多次遇到此错误,这是由于将大量资源(大于 3MB)从服务器传输到客户端。

          【讨论】:

          • 您对此有什么解决办法吗?如果可以,请分享您是如何解决的。
          • @UtkarshaG 压缩和缩小 css、js 文件。
          • 这发生在我身上,因为我有一个 select2,里面有 ~4000 个 SelectListItems(键值对)。不知从何而来,我刚开始在第一次加载时收到 HTTP2 协议错误。当我第二次点击刷新页面时加载正常。我只传递了 193kb 的数据,但也许协议不喜欢庞大的选择列表。
          【解决方案12】:

          我的团队在我们提供的单个 javascript 文件中看到了这一点。其他所有文件都运行良好。我们从http2 切换回http1.1,然后是net::ERR_INCOMPLETE_CHUNKED_ENCODINGERR_CONTENT_LENGTH_MISMATCH。我们最终发现有一个公司过滤器 (Trustwave) 错误地检测到“信息泄漏”(我们怀疑它在我们的文件/文件名中检测到类似于社会安全号码的东西)。让公司调整此过滤器解决了我们的问题。

          【讨论】:

            【解决方案13】:

            目前正在修复此错误:https://chromium-review.googlesource.com/c/chromium/src/+/2001234

            但它帮助了我,改变了 nginx 设置:

            • 开启 gzip;
            • add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
            • 过期;

            在我的例子中,Nginx 充当 Node.js 应用程序的反向代理。

            【讨论】:

            【解决方案14】:

            我们在具有长 Base64 字符串的页面上遇到了这个问题。出现问题是因为我们使用 CloudFlare。

            详情:https://community.cloudflare.com/t/err-http2-protocol-error/119619

            论坛帖子的关键部分:

            在多个浏览器上对隐身标签进行进一步测试后,然后 将代码从 BASE64 更改为真实的 .png 图像, 在任何浏览器中,问题再也没有发生过。 .png 大约有 500kb 在成为 base64 之前,CloudFlare 存在大量的问题 同一行上的文本(因为 base64 是一个长字符串)作为代理 域和heroku。前面说了,直接打 Heroku url 也从未发生过这个问题。

            临时破解是在 CloudFlare 上禁用 HTTP/2。

            希望其他人可以提出更好的解决方案,不需要在 CloudFlare 上禁用 HTTP/2。

            【讨论】:

            • 我们遇到同样的事情,但不是因为 cloudflare:我们只是有太多长的 base64 字符串图像
            【解决方案15】:

            对于我的情况,此错误是由于在使用 ORM 进行父/子关系时从服务器发送的 json 中的循环引用引起的。所以快速简单的解决方案是

            JsonConvert.SerializeObject(myObject, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore })
            

            更好的解决方案是创建不包含两边(父/子)引用的 DTO。

            【讨论】:

              【解决方案16】:

              在研究了一些我认为导致 24 错误的错误之后,我终于能够解决这个错误。我访问了网络上的所有页面。我很高兴地说我找到了解决方案。 如果您使用的是 NGINX,则将 gzip 设置为关闭并在服务器块中添加 proxy_max_temp_file_size 0;,如下所示。

               server {
                ...
                ...
                gzip off;
                proxy_max_temp_file_size 0;
                location / {
                  proxy_pass http://127.0.0.1:3000/;
                ....
              

              为什么?因为实际发生的是所有内容都被压缩了两次,我们不希望这样,对吧?!

              【讨论】:

              • 欣赏这个!我认为在我的特殊情况下关闭gzip 是缺少的步骤。我在 nginx 后面运行一个快速应用程序,并且只会在.css/.js 上得到错误,并非总是如此,可能是 1/2 的时间。这成功了!
              • 只是 proxy_max_temp_file_size 0;声明对我来说很好。
              【解决方案17】:

              默认情况下,nginx 将上传大小限制为 1MB。

              使用client_max_body_size,您可以设置自己的限制,如

              location /uploads {
                  ...
                  client_max_body_size 100M;
              } 
              

              您也可以在 http 或服务器块上设置此设置 (See here)。

              这解决了我的 net::ERR_HTTP2_PROTOCOL_ERROR 问题

              【讨论】:

                【解决方案18】:

                我还有一个案例导致了此处尚未提及的 ERR_HTTP2_PROTOCOL_ERROR。我在 IOC (Unity) 中创建了一个交叉引用,其中 A 类引用 B 类(通过几层),B 类引用 A 类。我的设计确实很糟糕。但是我为从类 B 调用的类 A 中的方法创建了一个新的接口/类,并且清除了它。

                【讨论】:

                  【解决方案19】:

                  就我而言,现在需要 PHP 7.4 的是 WordPress,而我运行的是 7.2。
                  我一更新,错误就消失了。


                  又发生了,这次是广告拦截器不喜欢我的图片名称(yt.pngig.pngurl.png)。我添加了一个前缀,一切正常。

                  【讨论】:

                    【解决方案20】:

                    我在使用服务器发送事件时遇到了这个问题。当我注意到我用来启动连接的域名包含一个斜杠时,问题就解决了,例如https://foo.bar.bam/ 失败,ERR_HTTP_PROTOCOL_ERRORhttps://foo.bar.bam 工作。

                    【讨论】:

                      【解决方案21】:

                      在我的例子中(Windows 上的 nginx 代理应用程序,同时自己提供静态资产)页面显示了多个资产,包括 14 张更大的图片;恰好在 60 秒后,其中大约 5 张图像显示了这些错误;在我的情况下,默认的 send_timeout 为 60 秒,导致这些图像请求失败;增加 send_timeout 使其工作

                      我不确定是什么导致 Windows 上的 nginx 为这些文件提供如此缓慢的服务 - 它只有 11.5MB 的资源,nginx 需要将近 2 分钟才能提供服务,但我想它是另一个线程的主题

                      【讨论】:

                        【解决方案22】:

                        我不相信这是问题,但通过 cPanel 我注意到 PHP 版本是 5.6 并且将其更改为 7.3 似乎可以解决它。这是针对 WordPress 网站的。我注意到我可以访问图像和通用 PHP 文件,但加载 WordPress 本身会导致错误。

                        【讨论】:

                        【解决方案23】:

                        似乎很多问题都可能导致ERR_HTTP2_PROTOCOL_ERROR:在我的情况下,这是php 生成的标头Content-Type : text/plain 中的一个小语法错误。您可能会注意到冒号之前 的空格......就是这样。当冒号紧挨着像Content-Type: text/plain 这样的标题名称时,工作没有问题。只花了一百万小时才弄清楚...该错误仅发生在 Chrome 上,Firefox 加载该对象时没有抱怨。

                        【讨论】:

                          【解决方案24】:

                          如果只是重新启动,例如 Chrome Canary,使用新的配置文件可以解决问题,那么肯定有 是"victim" of a failed Chrome Variation!是的,有办法在 Chrome 的现场测试中选择不成为 Guinea pig

                          【讨论】:

                            【解决方案25】:

                            就我而言 header 参数不能设置 null 或空字符串

                            {
                             'Authorization': Authorization  //Authorization can't use null or ''
                            }
                            

                            【讨论】:

                              【解决方案26】:

                              对于那些从搜索引擎登陆的人。

                              我最近遇到了这个问题,虽然不是 PHP,而是 .NET 和 Angular。我在这里和 IIS 等的 MS 支持论坛上尝试了绝大多数建议。最后我不得不通过旧的控制面板重新安装/修复 IIS Express(这会恢复开发证书,我实际上并没有使用 IIS Express)并在应用程序的 HTTPS 绑定下禁用 HTTP/2。当然,这仅适用于开发环境。

                              【讨论】:

                              • 是的,只需禁用 HTTPS(在应用程序>属性>调试中取消选中启用 SSL)即可解决问题。但如果您想继续使用 HTTPS,您可能需要深入挖掘。
                              【解决方案27】:

                              就我而言,问题在于 Bitdefender 为我提供了本地 ssl 证书,而该网站仍然没有证书。

                              当我禁用 Bitdefender 并重新加载页面时,加载了实际有效的服务器 ssl 证书,并且 ERR_HTTP2_PROTOCOL_ERROR 消失了。

                              【讨论】:

                                猜你喜欢
                                • 2017-08-06
                                • 1970-01-01
                                • 2011-02-04
                                • 2020-07-23
                                • 2020-03-25
                                • 2020-07-13
                                • 1970-01-01
                                • 2023-03-10
                                相关资源
                                最近更新 更多