HTTPQUERY
Русский

Content-Length

Применение

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

Когда сервер отправляет ответ с известным размером тела, заголовок Content-Length позволяет клиенту выделить нужный объём памяти и показывать точные индикаторы прогресса во время загрузки. Расхождение между объявленной длиной и фактическим размером тела говорит об обрезанной или повреждённой передаче.

Этот заголовок взаимоисключающий с Transfer-Encoding: chunked. Когда сервер передаёт потоком ответ неизвестного размера, фиксированную длину содержимого заменяет chunked-кодирование. В HTTP/2 и HTTP/3 границы сообщений определяются кадрированием на уровне протокола, но Content-Length остаётся допустимым для проверки размера тела.

Значение — одно неотрицательное целое число, обозначающее количество октетов (байтов) в теле сообщения.

Пример

Сервер возвращает JSON-ответ размером 3495 байт. Клиент считывает ровно 3495 байт, прежде чем счесть сообщение завершённым.

Content-Length: 3495

POST-запрос отправляет тело формы. Заголовок Content-Length сообщает серверу, сколько байтов ожидать в теле запроса.

POST /submit HTTP/1.1
Host: example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field=value&other=something

Ответ, использующий chunked transfer encoding, не содержит заголовка Content-Length вовсе. Приоритет имеет заголовок Transfer-Encoding.

Transfer-Encoding: chunked

Диагностика

Сбои передачи и ошибки соединения часто сводятся к неверному или конфликтующему значению Content-Length.

Передача прервана или файл загружен частично. Клиент получает меньше байтов, чем объявлено в Content-Length, и сообщает об обрезанном ответе. Частые причины: источник закрывает соединение раньше времени, тайм-аут прокси обрывает передачу или сервер неверно вычисляет размер тела. Выполните curl -v https://example.re/file и сравните значение заголовка Content-Length с фактически полученными байтами (они показаны в сводке по передаче). Расхождение подтверждает проблему.

Одновременно присутствуют chunked-кодирование и Content-Length. Отправка Transfer-Encoding: chunked и Content-Length в одном ответе нарушает спецификацию HTTP. Клиенты обязаны игнорировать Content-Length при наличии Transfer-Encoding, но не все реализации следуют этому правилу. При использовании chunked-кодирования удаляйте Content-Length. В nginx chunked-кодирование применяется автоматически, когда размер тела неизвестен, и в этом случае nginx не отправляет Content-Length. Собственный код приложения или промежуточное ПО, устанавливающее оба заголовка, требует исправления.

Content-Length становится неверным после изменения тела промежуточным ПО. Промежуточное ПО, внедряющее содержимое (скрипты аналитики, токены безопасности, панели отладки), меняет размер тела, не обновляя Content-Length. Браузер либо обрезает видимое содержимое, либо ждёт байты, которые так и не приходят. Перенесите вычисление Content-Length на завершающий этап, после всех изменений тела. В Express.js промежуточное ПО compression делает это автоматически. В самописных конфигурациях удалите Content-Length и положитесь на chunked-кодирование.

Ответ на HEAD несёт неверный Content-Length. Ответ на HEAD должен содержать тот же Content-Length, что и соответствующий ответ на GET, но без тела. Некоторые фреймворки формируют ответы на HEAD с Content-Length, равным 0, или не отправляют этот заголовок вовсе. Проверьте, сравнив curl -I https://example.re/resource (HEAD) с curl -s -o /dev/null -w ’%{size_download}’ https://example.re/resource (размер тела при GET). Несовпадающие значения ломают менеджеры загрузок и кэширующие прокси, которые определяют размер ресурса по HEAD.

Диагностика проблем с Content-Length с помощью curl. Выполните curl -v https://example.re/resource, чтобы увидеть заголовок Content-Length и число переданных байтов в подробном выводе. Строка Content-Length: N показывает объявленный размер. В конце bytes received показывает фактическую передачу. Добавьте -o /dev/null, чтобы отбросить тело и сосредоточиться на заголовках. Для сжатых ответов помните, что Content-Length отражает размер в сжатом виде, а не исходный размер.