О чем net::ERR_HTTP2_PROTOCOL_ERROR?
В настоящее время я работаю над веб-сайтом, который вызывает net::ERR_HTTP2_PROTOCOL_ERROR 200
ошибка в Google Chrome. Не знаю точно, что может спровоцировать эту ошибку, просто заметил, что она выскакивает только при доступе к сайту по HTTPS. Я не могу быть на 100% уверен, что это связано, но похоже, что это мешает правильному выполнению javascript.
Например, происходит следующий сценарий:
Я захожу на сайт по HTTPS
Мой канал Twitter, интегрированный через https://publish.twitter.com/, вообще не загружается
Я могу заметить в консоли ERR_HTTP2_PROTOCOL_ERROR
Если я удалю код для загрузки ленты Twitter, ошибка останется
Если я захожу на сайт по протоколу HTTP, появляется лента Twitter и ошибка исчезает.
Google Chrome - единственный веб-браузер, вызывающий ошибку: он хорошо работает как в Edge, так и в Firefox.
(NB: я пробовал с Safari, и у меня есть похожийkcferrordomaincfnetwork 303
ошибка)
Мне было интересно, может ли это быть связано с заголовком, возвращаемым сервером, поскольку в ошибке есть упоминание "200", а страница 404 / 500 ничего не запускает.
Дело в том, что ошибка вообще не документирована. Поиск в Google дает очень мало результатов. Более того, я заметил, что он появляется в самых последних выпусках Google Chrome; ошибка не появляется на v.64.X, но появляется на v.75+ (независимо от ОС; я работаю на Mac tho).
Любая подсказка на этом этапе для исследования будет с радостью оценена!
Заранее спасибо.
Тристан
Изменить 1: может быть связано с веб-сайтом OK в Firefox, но не в Safari (ошибка kCFErrorDomainCFNetwork 303) ни Chrome (net::ERR_SPDY_PROTOCOL_ERROR)
Изменить 2: Результаты дальнейших исследований следующие:
- ошибка не появляется на той же странице, если сервер возвращает 404 вместо 2XX
- ошибка не появляется на локальном компьютере с сертификатом HTTPS
- ошибка появляется на другом сервере (оба OVH), который использует другой сертификат
- ошибка появляется независимо от того, какая версия PHP используется, от 5.6 до 7.3 (используемый фреймворк: Cakephp 2.10)
Изменить 3: как и было запрошено, ниже приведен возвращаемый заголовок для сбойного ресурса, который представляет собой всю веб-страницу. Даже если ошибка запускается на каждой странице с 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
Изменить 4: Попытка углубиться в инструменты 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
Я читал в этом посте: " В HTTP/2, если клиент хочет прервать запрос, он отправляет RST_STREAM. Когда сервер получает RST_STREAM, он перестанет отправлять кадры DATA клиенту, тем самым останавливая ответ. (или загрузка). Соединение по-прежнему можно использовать для других запросов, и запросы / ответы, которые были одновременными с тем, который был прерван, могут продолжать выполняться. [...] Возможно, что к тому времени, когда RST_STREAM перейдет из клиент к серверу, все содержимое запроса находится в пути и будет доставлено клиенту, который его отбросит. Однако для большого содержимого ответа отправка RST_STREAM может иметь хорошие шансы прибыть на сервер до того, как все содержимое ответа отправляется, что позволяет сэкономить трафик ".
Описанное поведение такое же, как и то, что я наблюдаю. Но это будет означать, что виноват браузер, и тогда я не пойму, почему это происходит на двух идентичных страницах, одна из которых имеет заголовок 200, а другая - 404 (то же самое происходит, если я отключу JS).
47 ответов
Я не понял, что именно происходит, но нашел решение.
Особенность CDN из OVH был виновником. Он был установлен на моем хост-сервисе, но отключен для моего домена, потому что он мне не нужен.
Как-то при включении все работает.
Я думаю, что это заставляет Apache использовать протокол HTTP2, но я не понимаю, что действительно было упоминание HTTP2 в каждом из моих заголовков, что, как я полагаю, означает, что сервер отвечал с использованием правильного протокола.
Таким образом, решение для моего конкретного случая состояло в том, чтобы включить опцию CDN на всех соответствующих доменах.
Если кто-то лучше понимает, что здесь могло произойти, не стесняйтесь делиться объяснениями.
В моем случае это было - на веб-сервере не осталось места на диске.
Исправление для меня заключалось в установке в IIS значения . Эту настройку можно найти в
system.applicationHost/webLimits
в редакторе конфигурации IIS. По умолчанию установлено значение
240
.
Я смог решить эту проблему, выполнив следующие действия:
- Я использовал инструмент
экспорта сетевого журнала Chrome в
chrome://net-export/
чтобы точно увидеть, что скрывается за ошибкой. Я запустил журнал, воспроизвел ошибку и остановил журнал. - Я импортировал журнал в средство просмотра журналов по адресу https://netlog-viewer.appspot.com/#import и увидел интересное событие под названием
HTTP2_SESSION_RECV_RST_STREAM
, с кодом ошибки8 (CANCEL)
.
- Я немного погуглил по термину «RST_STREAM» (который, по-видимому, является сокращенной формой «reset stream») и нашел обсуждение между некоторыми людьми, говорящими о настройке IIS под названием (обсуждение здесь: https://social.msdn.microsoft ). .com/Forums/en-US/aeb01c46-bcdf-40ed-a417-8a3558221137). Я также нашел другое обсуждение, в котором были некоторые дебаты о том, предназначен ли он для защиты от медленных атак HTTP DoS (slow drop) (обсуждение здесь: IIS 8.5 low minBytesPerSecond не работает против медленного HTTP POST). В любом случае, я узнал, что IIS использует, чтобы определить, следует ли отменить соединение, если оно не может поддерживать минимальную пропускную способность. Это актуально в тех случаях, когда один пользователь делает много запросов к большому ресурсу, и каждое новое соединение приводит к голоданию всех остальных незавершенных до такой степени, что некоторые из них могут упасть ниже порогового значения.
- Чтобы убедиться, что сервер отменял запросы из-за ошибки, я проверил журнал HTTPERR своего сервера по адресу
c:\windows\system32\logfiles\httperr
. Конечно, я открыл файл и выполнил текстовый поиск «MinBytesPerSecond», и для него было множество записей.
- Итак, после того, как я изменил на
0
, я больше не мог воспроизвести ошибку. Таким образом, похоже, что ошибка была вызвана тем, что мой сервер (IIS) отменил запрос, потому что пропускная способность моего сервера упала нижеminBytesPerSecond
порог.
Итак, для всех, кто читает это прямо сейчас, если вы не используете IIS, возможно, есть аналогичный параметр, связанный с минимальной пропускной способностью, с которым вы можете поиграть, чтобы увидеть, избавится ли он от
ERR_HTTP2_PROTOCOL_ERROR
ошибка.
Я наконец смог решить эту ошибку после исследования некоторых вещей, которые, как я думал, вызывают ошибку для 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/;
....
Почему? Потому что на самом деле все содержимое сжималось дважды, а мы этого не хотим, верно?!
Несколько недель меня тоже раздражала эта "ошибка":
net :: ERR_HTTP2_PROTOCOL_ERROR 200
В моем случае это произошло с изображениями, созданными PHP.
Это было в header()
уровень, и на этом в частности:
header ('Content-Length:'. Filesize($cache_file));
Он явно не вернул точный размер, поэтому я удалил его, и теперь все работает нормально.
Итак, Chrome проверяет точность данных, передаваемых через заголовки, и, если они не соответствуют, терпит неудачу.
РЕДАКТИРОВАТЬ
Я нашел почему content-length
через filesize
просчитывались: GZIP
сжатие активно для файлов PHP, поэтому исключение данного файла решит проблему. Поместите этот код в.htaccess
:
SetEnvIfNoCase Request_URI ^ / thumb.php no-gzip -vary
Работает и шапку держим Content-length
.
У меня возникла аналогичная проблема, я получал ERR_HTTP2_PROTOCOL_ERROR на одном из запросов HTTP GET.
Я заметил, что обновление Chrome было отложено, поэтому я обновил браузер Chrome до последней версии, и ошибка исчезла в следующий раз, когда я перезапустил браузер.
Я столкнулся с этим, потому что сервер http2 закрыл соединение при отправке большого ответа в Chrome.
Зачем? Потому что это просто настройка сервера http2 с именем WriteTimeout.
У меня была эта проблема, когда у меня был сервер Nginx, который открывал приложение node-js внешнему миру. Nginx сделал файл (css, js, ...) сжатым с помощьюgzip
и с Chrome это выглядело так же.
Проблема решена, когда мы обнаружили, что сервер node-js также сжимает контент с помощью gzip. Так или иначе, это двойное сжатие привело к этой проблеме. Отмена сжатия node-js решила проблему.
Моя проблема заключалась в том, что мой токен доступа был слишком большим, что делало заголовок слишком большим, поэтому я провел рефакторинг его содержимого, чтобы исправить ошибку.
Мы столкнулись с этой проблемой на страницах с длинными строками Base64. Проблема возникает из-за того, что мы используем CloudFlare.
Подробности: https://community.cloudflare.com/t/err-http2-protocol-error/119619.
Ключевой раздел из сообщения на форуме:
После дальнейшего тестирования на вкладках инкогнито в нескольких браузерах, а затем внесения изменений в код с BASE64 на реальное изображение.png, проблема больше не возникала ни в каком браузере..Png имел около 500 КБ до того, как стать base64, поэтому CloudFlare имеет проблемы с огромными строками текста на одной строке (поскольку base64 - это длинная строка) в качестве прокси между доменом и heroku. Как упоминалось ранее, при прямом обращении к URL-адресу Heroku также никогда не возникало проблем.
Временный хакер - отключить HTTP/2 в CloudFlare.
Надеюсь, кто-то другой сможет предложить лучшее решение, которое не требует отключения HTTP/2 в CloudFlare.
Эта ошибка в настоящее время исправляется: 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.
В моем случаеnet::ERR_HTTP2_PROTOCOL_ERROR 200
было вызвано балансировщиком нагрузки (AWS), который завершает простаивающие соединения через 60 секунд.
Если к моменту истечения периода ожидания простоя данные не были отправлены или получены , балансировщик нагрузки закрывает соединение. Чтобы обеспечить время завершения длительных операций, таких как загрузка файлов, отправляйте не менее 1 байта данных до истечения каждого периода ожидания простоя и при необходимости увеличивайте продолжительность периода ожидания простоя.
А прерванное соединение представляло собой конечную точку vaadin vaadin8 с длинным опросом , которая не отправляет данные, если на бэкэнде нет событий. Подробнее об этом читайте в этом сообщении в блоге https://mvysny.github.io/Vaadin8-push-issues/ , которое мне очень помогло.
Решение, которое я использовал , заключалось в установке параметра контекста.pushLongPollingSuspendTimeout
к58000
вweb.xml
Просто публикую здесь, чтобы люди знали, что ошибка ERR_HTTP2_PROTOCOL_ERROR в Chrome также может быть вызвана неожиданным ответом на запрос CORS .
В нашем случае запрос OPTIONS был успешным , но следующий PUT , который должен загрузить изображение в нашу инфраструктуру, был отклонен с ошибкой 410 (из-за отсутствия конфигурации, позволяющей загружать), в результате чего Chrome выдал ошибку ERR_HTTP2_PROTOCOL_ERROR.
При проверке в Firefox сообщение об ошибке было гораздо полезнее:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.[...] (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 410.
В этом случае я бы порекомендовал проверить альтернативный браузер.
Net ::ERR_HTTP2_COMPRESSION_ERROR - WORDPRESS
Хорошо, надеюсь, это многим поможет. Я испытываю это уже много недель. Прошу прощения, потому что я использую WordPress.
net::ERR_HTTP2_COMPRESSION_ERROR встречается только в Chrome:Incognito.
У меня есть Cloudflare для моего CDN и кеширования HTML - и W3 Total Cache - для минимизации js, css и Page Cache, OP-Cache, Object Cache, Browser Cache.
теперь, после бесчисленных попыток устранения неполадок, я обнаружил проблему при отключении "Кеша браузера", после этого я исправил проблему, когда
Я изменил кеш браузера (перейти на боковую панель)
найдите ("Политика HTTP Strict Transport Security"), убедитесь, что она отмечена. под этой директивой установите значение - max-age=EXPIRES_SECONDS; includeSubDomain: предварительная загрузка
обратите внимание, что я использую поддомен.
Я сталкивался с этой ошибкой несколько раз, и это было связано с передачей больших ресурсов (более 3 МБ) с сервера на клиент.
По умолчанию nginx ограничивает размер загрузки до 1 МБ.
С участием
client_max_body_size
вы можете установить свой собственный лимит, как в
location /uploads {
...
client_max_body_size 100M;
}
Вы можете установить этот параметр также в блоке http или server (см. Здесь).
Это устранило мою проблему с net::ERR_HTTP2_PROTOCOL_ERROR
В нашем случае причиной был недопустимый заголовок. Как упоминалось в Edit 4:
- взять бревна
- в средстве просмотра выберите События
- выбрал HTTP2_SESSION
Ищите нечто подобное:
HTTP2_SESSION_RECV_INVALID_HEADER
-> error = "Недействительный символ в имени заголовка."
-> header_name = "charset = utf-8"
Похоже, многие проблемы могут вызвать
ERR_HTTP2_PROTOCOL_ERROR
: в моем случае это была небольшая синтаксическая ошибка в заголовке, сгенерированном php,
Content-Type : text/plain
. Вы могли заметить пробел перед двоеточием ... вот и все. Работает без проблем, когда двоеточие стоит рядом с названием заголовка, например
Content-Type: text/plain
. На то, чтобы разобраться, потребовался всего миллион часов ... Ошибка возникает только с Chrome, Firefox загрузил объект без жалоб.
Это случилось со мной, когда я зарегистрировал новое доменное имя, например, "новый" для example.com (new.example.com). Имя не могло быть разрешено временно в моем местонахождении в течение нескольких часов, в то время как оно могло быть разрешено за границей. Итак, я использовал прокси-сервер, чтобы протестировать сайт, на котором я увиделnet::ERR_HTTP2_PROTOCOL_ERROR
в консоли Chrome для некоторых сообщений AJAX. Через несколько часов, когда имя можно было изменить локально, эта ошибка просто исчезла.
Я думаю, что причина этой ошибки в том, что запросы AJAX не были перенаправлены моим прокси, он просто посещает веб-сайт, который не был разрешен моим локальным преобразователем DNS.
Для меня это было связано с полным дисковым пространством.
Мое приложение (сервер) работало на докере. Очистил место, и он начал работать.
Я столкнулся с этой проблемой, работая с событиями, отправленными сервером. Проблема была решена, когда я заметил, что доменное имя, которое я использовал для инициации соединения, содержит косую черту в конце, например
https://foo.bar.bam/
потерпел неудачу с
ERR_HTTP_PROTOCOL_ERROR
пока
https://foo.bar.bam
работал.
Я не уверен, что это была проблема, но через cPanel я заметил, что версия PHP была на 5.6, и изменение ее на 7.3, похоже, исправило ее. Это было для сайта WordPress. Я заметил, что могу получить доступ к изображениям и общим файлам PHP, но загрузка WordPress сама по себе вызвала ошибку.
Если простой перезапуск, например, Chrome Canary со свежим профилем решает проблему, то вы, несомненно, являетесь версии «жертвой» неудачнойChrome ! Да, есть способы , чтобы отказаться от того , чтобы быть свинками в тестировании в Chrome поля.
В моем случае параметры заголовка не могут устанавливать нулевую или пустую строку
{
'Authorization': Authorization //Authorization can't use null or ''
}
У меня возникла такая же проблема в C# NET Core 6. Я записывал результаты в ответ тела с помощью методаWriteAsync
и возвращаясь сTask.CompletedTask
Как показано ниже:
await ctx.Response.WriteAsync("something to return");
return Task.CompletedTask;
И изменил его на код ниже:
await ctx.Response.WriteAsync("something to return");
return ctx.Response.CompleteAsync();
И теперь он работает нормально.
Судя по всему, вам нужно сообщить объекту Response, что вы закончили его редактирование.
В моем случае проблема заключалась в том, что Bitdefender предоставил мне локальный ssl-сертификат, когда на сайте еще не было сертификата.
Когда я отключил Bitdefender и перезагрузил страницу, был загружен действительный сертификат ssl сервера, а ERR_HTTP2_PROTOCOL_ERROR исчезла.
Чтобы добавить к длинному списку, казалось бы, произвольных причин, вот моя:
Сценарий
- Миграция 32-разрядного классического веб-сайта ASP, работающего на Windows Server 2012, который использует 32-разрядные драйверы MDB OleDB для доступа к базе данных Access.
- Переход на Windows Server 2022.
- Попытка улучшить ситуацию и установить 64-битные драйверы OleDB MDB, изменив строку подключения с
Microsoft.Jet.OLEDB.4.0
кMicrosoft.ACE.OLEDB.12.0
затем запустите приложение в 64-битном пуле приложений в IIS.
Это вызывает случайноеERR_HTTP2_PROTOCOL_ERROR
ошибки из-за сбоя пула приложений.
Как исправить
Исправление было:
- Удалите 64-битные драйверы MDB OleDB.
- Установите 32-разрядные драйверы MDB OleDB.
- Снова переключите пул приложений на 32-разрядную версию.
Я очень надеюсь, что наконец-то найду время перенести все это на какое-нибудь современное ядро ASP.NET, но на данный момент это было самое быстрое решение.
В моей ситуации эта ошибка была вызвана наличием циклических ссылок в json, отправленных с сервера при использовании ORM для отношений родитель / потомок. Итак, быстрое и простое решение было
JsonConvert.SerializeObject(myObject, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore })
Лучшее решение - создать DTO, которые не содержат ссылок с обеих сторон (родительский / дочерний).
В моем случае (nginx в Windows проксирует приложение, обслуживая статические ресурсы самостоятельно), страница показывала несколько ресурсов, включая 14 больших изображений; эти ошибки были показаны примерно для 5 из этих изображений ровно через 60 секунд; в моем случае это было значение send_timeout по умолчанию, равное 60 с, что приводило к сбою этих запросов изображения; увеличение send_timeout заставило его работать
Я не уверен, что заставляет nginx в Windows так медленно обслуживать эти файлы - это всего лишь 11,5 МБ ресурсов, на обслуживание которых у nginx уходит почти 2 минуты, но я предполагаю, что это зависит от другого потока
Эта проблема также может возникнуть, если у вас есть перезапуск пула приложений (в IIS) при загрузке страницы, загрузка которой занимает много времени (например, она содержит сложные запросы, выполнение которых требует времени).