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

Java
После столь долгого использования HTTP вы понимаете, что такое Content-Length и Transfer-Encoding?

Ряд мыслей, вызванных проблемами, вызванными Content-Length

Адрес статьи:blog.Park Ruiqing.com/2019/09/08/…

Некоторое время назад я разрабатывал API-шлюз, и при отладке с почтальоном был тайм-аут.После расследования было установлено, что данные запроса были обработаны.Content-LengthПроблема вызвана несоответствием факту, поэтому есть эта статья.

предисловие

Content-Length, Длина HTTP-сообщения, сдесятичное числоуказаноколичество октетовВ общем, фреймворк делает много работы, и мы редко обращаем внимание на эту часть, но в единичных случаях это бывает.Content-LengthВ отличие от фактической длины сообщения программа может иметь странные исключения, такие как:

  • Нет ответа до таймаута.
  • Запрос был усечен, а следующий запрос был проанализирован не по порядку.

Что такое 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-Length10, то запрошенное сообщение будет воспринято как:param=piao, как показывает на рисунке:

Но, это только случай, конечно нет, посмотрим какие непредвиденные вещи произойдут со вторым запросом, как показано на рисунке:

При двух последовательных запросах первое сообщение усекалось, а второй раз ожидаемого усечения не произошло, но сервер выдал исключение:Request method 'ruiqingPOST' not supported.Шип не раздражает (ノ)゚Д゚( )

ТотruiqingPOSTЧто за феерический метод???На данный момент с выработанной многолетним опытом разработки (DEBUG) чувствительностью можно примерно догадаться что оставшиеся сообщения были перехвачены в последнем запросе, а появились в этом запросе. out wireshark Для проверки, как показано на рисунке:

Причина такой ситуации открыта.Connection:keep-aliveЕсли вы используетеConnection:close, результатом является то, что каждый запрос усекается, но не возникает путаницы при синтаксическом анализе (например, объединение оставшихся сообщений последнего времени в последующие сообщения запроса).

[Уведомление об авторских правах]
Эта статья была опубликована вБлог Пак Жуцин, перепечатка для некоммерческого использования разрешена, но перепечатка должна сохранить оригинального автораПарк Жуйцини ссылка:blog.piaoruiqing.com. Если есть какие-либо переговоры или сотрудничество с точки зрения авторизации, пожалуйста, свяжитесь с адресом электронной почты:piaoruiqing@gmail.com.

Что делать, если вы не уверены в значении 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.