Кодировка передачи по частям - поведение браузера

Я пытаюсь отправить данные в чанкованном режиме. Все заголовки установлены правильно, а данные кодируются соответствующим образом. Браузеры распознают мой ответ как фрагментарный, принимая заголовки и начинают получать данные.

Я ожидал, что браузер обновит страницу на каждом полученном чанке, вместо этого он ждет, пока все чанки будут получены, а затем отобразит их все. Это ожидаемое поведение?

Я ожидал увидеть каждый кусок отображается сразу после его получения. Когда используешь curlкаждый блок отображается сразу после его получения. Почему то же самое не происходит с браузерами GUI? Они используют какую-то буферизацию / кеш?

Я установил Cache-Control заголовок к no-cache, так что не уверен, что речь идет о кеше.

2 ответа

Решение

Браузеры afaik нуждаются в некоторой полезной нагрузке, чтобы начать рендеринг чанков по мере их поступления.
Керл, конечно, исключение.

Попробуйте отправить около 1 КБ произвольных данных перед первым порцией.

Если вы все делаете правильно, браузеры должны отображать фрагменты так, как они получены.

Исправьте ваши заголовки.


1) По состоянию на 2019 год, если вы используете Content-type: text/html, в Chrome не выполняется буферизация.


2) Если вы просто хотите транслировать текст, аналогично text/plain, а затем просто используя Content-type: text/event-stream также отключит буферизацию.


3) Если вы используете Content-type: text/plain, то Chrome по-прежнему буферизует 1 КиБ, если вы дополнительно не укажете X-Content-Type-Options: nosniff.

RFC 2045 указывает, что если нетContent-Type указано, Content-type: text/plain; charset=us-ascii следует предполагать

5.2. Значения по умолчанию для типа содержимого

Сообщения RFC 822 по умолчанию без заголовка MIME Content-Type принимаются этим протоколом как обычный текст в наборе символов US-ASCII, который может быть явно указан как:

Content-type: text/plain; charset=us-ascii

Это значение по умолчанию предполагается, если не указано поле заголовка Content-Type. Также рекомендуется использовать это значение по умолчанию при обнаружении синтаксически недопустимого поля заголовка Content-Type. При наличии поля заголовка MIME-Version и отсутствии какого-либо поля заголовка Content-Type принимающий пользовательский агент может также предположить, что намерением отправителя был простой текст US-ASCII. Обычный текст US-ASCII все еще может предполагаться при отсутствии MIME-версии или наличии синтаксически недопустимого поля заголовка Content-Type, но намерение отправителя могло быть другим.

Браузеры начнут буферизовать text/plain на определенную сумму, чтобы проверить, могут ли они определить, действительно ли отправленный контент представляет собой простой текст или какой-либо тип мультимедиа, например изображение, в случае Content-Type был опущен, что тогда равнялось бы text/plainТип содержимого. Это называется анализом типа MIME.

Обнюхивание типа MIME определяется Mozilla как:

В отсутствие типа MIME или в некоторых случаях, когда браузеры считают, что они неверны, браузеры могут выполнять сниффинг MIME - угадывая правильный тип MIME, просматривая байты ресурса.

Каждый браузер выполняет анализ MIME по-своему и при разных обстоятельствах. (Например, Safari будет проверять расширение файла в URL-адресе, если отправленный тип MIME не подходит.) Существуют проблемы безопасности, поскольку некоторые типы MIME представляют исполняемое содержимое. Серверы могут предотвратить прослушивание MIME, отправив заголовок X-Content-Type-Options.

Согласно документации Mozilla:

В X-Content-Type-Options HTTP-заголовок ответа - это маркер, используемый сервером, чтобы указать, что типы MIME, объявленные в Content-Typeзаголовки не должны изменяться и соблюдаться. Это позволяет отказаться от сниффинга типа MIME, или, другими словами, это способ сказать, что веб-мастера знали, что они делают.

Поэтому добавляя X-Content-Type-Options: nosniff заставляет это работать.

Браузер может обрабатывать и отображать данные по мере поступления, независимо от того, отправляются ли данные по частям или нет. Будет ли браузер отображать данные ответа, будет зависеть от структуры данных и от того, какой тип буферизации он использует. Например, прежде чем браузер сможет отобразить изображение, ему нужно иметь документ (или достаточно документа), таблицу стилей и т. д.

Разделение на блоки в основном полезно, когда длина ресурса неизвестна во время генерирования ответа ресурса ("Content-Length" не может быть включена в заголовки ответа), и сервер не хочет закрывать соединение после ресурс передан.

Другие вопросы по тегам