В HTTP/1.1 есть два вида передачи тела:
- Целый
- Раздробленный*
* перевёл как мог, я ебу как их локализировать. В оригинале - chunked. Да и целым я тоже хуй его, корректно ли кликать.
С целой передачей, у нас есть Content-Length, и там конкретное количество октетов*, содержащихся в теле запроса**.
* в сетевой разработке предпочитают применять понятие "октет битов" вместо "байт", поскольку, в отличии от "байт", слово "октет" чётко говорит о том, что битов там 8. А байт - он и из 6, и из 9, и из 16 битов состоять может (CDC6600, PDP-10, PDP-11).
** В rfc2616 просят игнорировать CRLF перед методом запроса, поскольку некоторые старые и хуёвые клиенты после тела добавляли неучтённые в длине CRLF. Сия помарка осталась там и до сих пор.
С chunked всё интереснее. Он сделан для ситуаций, когда длина тела заранее неизвестна, посему мы его льём "потоком". А именно - кусками - откуда и происходит его название. Каждый кусок - это
<hex len>\r\n<data>\r\n. Шестнадцатиричная длина, перенос строки*, данные, перенос строки. Тело считается завершённым тогда, когда мы получаем чанк с нулевой длиной.
* CRLF остался стандартным разделителем и до сих пор в HTTP/1.1, и пошло это ещё со времён HTTP/0.9. Unix (точнее, все unix-like уже на тот момент - линукс, бсд, OSX) издревна понимал просто LF (
\n), а вот винда, как обычно, отличилась, и хотела именно CRLF (
\r\n). Поскольку упор был на гипертекстовую природу протокола, дабы быть человекочитаемым, так оно и закрепилось вплоть до самых последних rfc. Пускай некоторые имплементации и поддерживают LF-only (как, например, моя - минутка
саморекламы), но такое поведение конформным не считается. В ABNF-нотации в стандарте синтаксис определяет конкретно и только CRLF.
Им удобно отдавать, например, потоковый JSON ответ с сервера. Ещё очень удобно таким образом файлы лить, но их лучше совать целиком. Потому что тогда за цену 1.5 сисколлов* мы можем задействовать
sendfile(2), находясь под линуксом. А я нахожусь под линуксом, мне поебать. Zero-copy передача файла - это вот очень хорошо, на самом деле. Линусу это, кстати, не нравится.
* 1 - чтобы размер файла получить, 0.5 - заголовки придётся записать отдельно от тела, но для файлов больше пары килобайт таких записей всё равно будет несколько - в результате всё равно остаёмся в выигрыше.
А ещё, благодаря такому стримингу тела, можно удобно воротить нотификации и лонгполлинг без прибегания к вебсокетам, да. Единственное - IDLE подключения всё ещё мрут по таймауту.
В более новых стандартах, у чанков ещё и появились экстеншены. Пары ключ-значение, идущие сразу после длины блока, разделённые через
;. С ними можно получить практически HTTP внутри HTTP. Жаль только мало кто их поддерживает - с точки зрения дизайна вебфреймворка/клиента ебливо. Правда, AWS S3 их использует как раз - и это проблема. Не для меня, конечно, а для тех, кто попытается распопробовать мою индигу с AWS.
—
Вообще, я это всё писал, чтобы погрузить в детали перед тем, как свою проблему вывалить. Но сработал прекраснейший метод утёнка, а столь распрекраснейший текст грешен же, коли в небытие канет. Нахуй я его тогда писал, иными словами. Посему наслаждайтесь вбросом без контекста, господа.