После столь долгого использования HTTP вы понимаете Content-Length?

HTTP

Резюме:Понимание протокола HTTP...

Ряд мыслей, вызванных проблемой, вызванной 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будет игнорироваться.

Ссылаться на

Уведомление об авторских правах

Эта статья была опубликована вБлог Пак Жуцин, перепечатка для некоммерческого использования разрешена, но перепечатка должна сохранить оригинального автораПарк Жуйцини ссылка: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 и многие другие бренды. приветствую всехБесплатная пробная версия!