Резюме:Понимание протокола HTTP...
- оригинал:После столь долгого использования HTTP вы понимаете, что такое Content-Length и Transfer-Encoding?
- автор:Блог Пак Жуцин
Ряд мыслей, вызванных проблемой, вызванной Content-Length: Некоторое время назад я разрабатывал API-шлюз, и при отладке с почтальоном был тайм-аут.После расследования было установлено, что данные запроса были обработаны.
Content-LengthПроблема вызвана несоответствием факту, поэтому есть эта статья.
Content-Length, Длина HTTP-сообщения, сдесятичное числоуказаноколичество октетовВ общем, фреймворк делает много работы, и мы редко обращаем внимание на эту часть, но это бывает в единичных случаях.Content-LengthВ отличие от фактической длины сообщения программа может иметь странные исключения, такие как:
- Нет ответа до таймаута.
- Запрос был усечен, а следующий запрос был проанализирован не по порядку.
Content-Lengthдлина HTTP-сообщения, сдесятичное числоуказаноколичество октетов, является общим полем в заголовках.Content-LengthДолжно быть точным, иначе возникнет исключение (в частности, это поле было необязательным в HTTP 1.0).
Content-LengthЗаголовок указывает размер тела сообщения в байтах, включая все кодировки содержимого, например, для текстовых файлов.gzipсжатый,Content-LengthЗаголовок относится к сжатому размеру, а не к исходному размеру.
Как работает Content-Length
Content-LengthДлина сообщения представлена десятичным числом, и сервер/клиент использует его, чтобы узнать длину сообщения, которое будет прочитано позже.
Если эта длина неверна, происходит следующее:
Content-Length > фактическая длина
Если Content-Length больше фактической длины, сервер/клиент будет ждать следующего байта после прочтения конца сообщения, и, естественно, ответа не будет до истечения времени ожидания.
Так же в ответном сообщенииContent-LengthПревышение фактической длины также имеет тот же эффект:
Content-Length
Если эта длина меньше фактической длины, сообщение первого запроса будет перехвачено, например, параметрparam=piaoruiqing, Content-Lengthравно 10, то сообщение этого запроса будет перехвачено как:param=piao, как показано на рисунке:
Но, это только случай, конечно нет, посмотрим какие непредвиденные вещи произойдут со вторым запросом, как показано на рисунке:
При двух последовательных запросах первое сообщение усекалось, а во второй раз ожидаемого усечения не произошло, но сервер выдал исключение:Request method 'ruiqingPOST' not supported.Шип не раздражает (ノ)゚Д゚( )
ЭтоruiqingPOSTЧто за феерический метод???На данный момент с выработанной многолетним опытом разработки (DEBUG) чувствительностью можно примерно догадаться что оставшиеся сообщения были перехвачены в последнем запросе, а появились в этом запросе. out wireshark Для проверки, как показано на рисунке:
Причина этого в том, что он включенConnection:keep-alive, если использоватьConnection:close, в результате каждый запрос усекается, но не возникает путаницы при синтаксическом анализе (например, вставка последнего оставшегося сообщения в последующее сообщение запроса).
Что делать, если вы не уверены в значении Content-Length
Content-Length首部指示出报文中实体主体的字节大小. 但如在请求处理完成前无法获取消息长度, 我们就无法明确指定Content-Length, 此时应该使用Transfer-Encoding: chunked
Что такое кодирование передачи: фрагментированное
Данные отправляются сериями блоков.Content-LengthЗаголовок в этом случае не отправляется.В начале каждого блока нужно добавить длину текущего блока в шестнадцатеричном виде, а затем\r\n, за которым следует сам фрагмент, за которым следует\r\nБлок завершения является обычным блоком, за исключением того, что его длина равна 0.
Transfer-Encoding: как работает фрагментация
Далее мы используем пример загрузки файла для обсужденияTransfer-Encoding: chunkedКак это работает Код сервера выглядит следующим образом:
Используйте postman, чтобы инициировать запрос, и wireshark, чтобы захватить пакет для просмотра, как показано на рисунке:
Разделенные данные хорошо видны в wirehark, и их структура примерно следующая: возвращаемое сообщение разделено на несколько блоков данных, каждый блок данных состоит из двух частей,长度 + 数据, обе части начинаются с CRLF (т.е.\r\n) в конце Блок завершения — это специальный блок данных, длина которого равна 0, как показано на рисунке:
Таким образом завершается блочное кодирование.В основном используется в следующих сценариях, то есть необходимо передать большое количество данных, но длину ответа нельзя получить до обработки запроса.Например, когда необходимо выполнить запрос из базы данных для получения данных генерируется большая HTML-таблица, требуется передать большое количество изображений и т. д.
-
Content-LengthЕсли оно существует и вступает в силу, оно должно быть правильным, иначе произойдет исключение (если оно больше фактического значения, истечет время ожидания, если меньше фактического значения, оно будет усечено и может вызвать путаницу. при последующем анализе данных) - Если сообщение содержит
Transfer-Encoding: chunkedбудет первыйContent-Lengthбудет игнорироваться.
Ссылаться на
- developer.mozilla.org
- Полное руководство по HTTP
Уведомление об авторских правах
Эта статья была опубликована вБлог Пак Жуцин, перепечатка для некоммерческого использования разрешена, но перепечатка должна сохранить оригинального автораПарк Жуйцини ссылка:blog.piaoruiqing.com, Если есть какие-либо переговоры или сотрудничество с точки зрения авторизации, пожалуйста, свяжитесь с почтовым ящиком: piaoruiqing@gmail.com.
О Фундебаге
FundebugСосредоточьтесь на JavaScript, апплете WeChat, мини-игре WeChat, апплете Alipay, React Native, Node.js и мониторинге ошибок онлайн-приложений Java в режиме реального времени. С момента официального запуска Double Eleven в 2016 году Fundebug обработал в общей сложности более 2 миллиардов ошибок.Платежеспособными клиентами являются Sunshine Insurance, Walnut Programming, Lizhi FM, Head 1:1, Weimai, Youth League Club и многие другие бренды. приветствую всехБесплатная пробная версия!