Ряд мыслей, вызванных проблемами, вызванными 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будет игнорироваться.
Если эта статья была вам полезна, ставьте лайк ( ̄▽ ̄)"
использованная литература
- developer.mozilla.org
- Полное руководство по HTTP
Рекомендуемое чтение:
Добро пожаловать в публичный аккаунт (код как поэзия):
Эта статья была опубликована вБлог Пак Жуцин, перепечатка для некоммерческого использования разрешена, но перепечатка должна сохранить оригинального автораПарк Жуйцини ссылка:blog.piaoruiqing.com. Если есть какие-либо переговоры или сотрудничество с точки зрения авторизации, пожалуйста, свяжитесь с адресом электронной почты:piaoruiqing@gmail.com.