Иногда данные, передающиеся с сервера, могут быть достаточно большими. И более того, мы можем не знать их конечный размер. Например, если нужно скачать архив или во время видео-трансляции.
Для решения этой проблемы можно загрузить данные полностью в оперативную память на сервере, вычислить Content-Length и осуществить передачу. После того как контент будет целиком принят браузером, тот его моментально отобразит.
Существует еще одно решение, которое позволяет надежно передавать данные, когда мы не знаем их конечный размер. По ссылке находится пример текста, который отрисовывается постепенно по мере того, как происходит передача данных. Для этого используется механизм передачи небольшими частями, чанками (англ. chunks), и специальный заголовок Transfer-Encoding со значением chunked.
В стандартном ответе мы получаем все body целиком и после этого его обрабатываем. Мы не можем обрабатывать его частями потому, что тогда будем вводить какие-то свои уникальные правила внутри протокола. Но при передаче чанками мы можем обрабатывать ответ до полного получения body.
Сделаем запрос к сайту:
telnet http.hexlet.app 80
GET /http-protocol/stream HTTP/1.1
host: http.hexlet.app
Connection: close
HTTP/1.1 200 OK
Date: Thu, 03 Oct 2024 17:20:10 GMT
Connection: close
Transfer-Encoding: chunked
8 # длина чанка
Chunk 1
8
Chunk 2
8
Chunk 3
8
Chunk 4
8
Chunk 5
0 # последний чанк нулевой длины
Обратите внимание, что заголовки, как всегда, отделяются от тела запроса переводом строки. В начале каждого чанка указывается его размер. За ним располагаются данные и в конце чанка делается перевод строки, затем идет следующий чанк и так далее. Таким образом можно передавать сколько угодно чанков, время ограничено только таймаутами внутри сервера.
Чтобы завершить передачу, нужно передать последний чанк, который должен быть нулевой длины. После него делается два перевода строки и запрос считается полностью переданным.
Формат сообщений
Для отделения записей размеров блоков (частей) от их содержания используется разделитель CRLF (как строка: «\r\n»; как байты в формате HEX: 0x0D, 0x0A). Длина блока — это размер содержания блока, разделители CRLF не учитываются, кроме тех, которые находятся в самих блоках.
Схематическое представление: <длина блока в HEX><CRLF><содержание блока><CRLF>
Последний блок строится по той же схеме, потому имеет следующий вид по причине отсутствия содержания: 0<CRLF><CRLF>
Стандарт также позволяет использовать в качестве разделителя только CR или только LF.
Дополнительные материалы
- Ссылка на изображение, передаваемое с помощью chunks (пример из видео)
- Chunked transfer encoding / Википедия
- Шестнадцатеричная система счисления (HEX) / Википедия
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.