HTML в HTTP-ответе: где именно находится код

Где находится HTML-код в структуре HTTP-ответа?

Структура HTTP-ответа (HTTP/1.1)

В HTTP/1.1 ответ представляет собой последовательность: статусная строка, затем заголовки, затем пустая строка, затем (опционально) тело сообщения.

Упрощённая схема:

+-------------------------------+
| status-line                   |
| headers...                    |
| (пустая строка)               |
| message-body (байты)          |
+-------------------------------+

Пример «сырого» ответа с HTML:

HTTP/1.1 200 OK
Date: Wed, 18 Feb 2026 17:49:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 89

<!doctype html>
<html>
  <head><title>Hi</title></head>
  <body>Hello</body>
</html>

HTML-код находится в теле (body/content) HTTP-ответа: он идёт после стартовой строки и заголовков и отделяется от них пустой строкой (CRLF CRLF).

То, что тело следует интерпретировать как HTML, обычно определяется заголовком Content-Type: text/html; ... (а также параметром charset, если он указан).

Таблица: где именно находится HTML

Часть ответаЧто этоГде находится HTML
Status lineВерсия протокола, код статуса, reason phraseНе здесь
HeadersМетаданные ответа (тип, длина, кеш, куки и т. п.)Не здесь, но тут обычно есть Content-Type
Пустая строкаРазделитель «заголовки/тело»Маркер, после которого начинаются байты HTML
Body (message-body/content)Полезная нагрузкаЗдесь лежит HTML (как последовательность байтов)
Даже если HTML выглядит как «текст», на уровне HTTP это всегда байты; «текстом» они становятся после выбора кодировки символов (charset) и декодирования.

Как понять, что тело — HTML

Ключевой сигнал — заголовок Content-Type, который сообщает медиатип представления в теле ответа.

Типичный вариант:

Content-Type: text/html; charset=utf-8

Типичные случаи, которые важно различать:

  • Content-Type: text/html; charset=utf-8 — ожидается HTML, кодировка UTF‑8.
  • Content-Type: application/xhtml+xml — ожидается XHTML (XML-режим), правила разбора и обработки ошибок отличаются.
  • Content-Type отсутствует или неверен — некоторые клиенты могут пытаться «угадать» тип по содержимому (sniffing), поведение зависит от клиента и политики безопасности.

Концептуальная цепочка обработки на стороне клиента:

  1. Получение байтов ответа.
  2. Отделение заголовков от тела по границе (в HTTP/1.1 это пустая строка).
  3. Определение типа данных по Content-Type (или эвристиками при проблемах с заголовком).
  4. Декодирование Content-Encoding, если присутствует (например, gzip/br), чтобы получить исходные байты контента.
  5. Применение charset для превращения байтов в текст.
  6. Передача текста HTML-парсеру.
Если включено сжатие (Content-Encoding: gzip или Content-Encoding: br), то в «сыром» трафике не будет виден читаемый HTML до распаковки.

Что меняется в HTTP/2 и HTTP/3

Смысл не меняется: HTML по-прежнему является содержимым тела ответа, а Content-Type по-прежнему описывает, как интерпретировать это содержимое.

Меняется формат передачи: вместо текстового сообщения с CRLF-разделителями (как в HTTP/1.1) используются бинарные кадры (frames) и потоки (streams), поэтому «пустая строка» как разделитель может отсутствовать на уровне передачи, хотя логическое разделение «заголовки/тело» сохраняется.

Практическое следствие:

  • В HTTP/1.1 начало HTML находится после \r\n\r\n.
  • В HTTP/2 и HTTP/3 HTML собирается из фрагментов данных тела (payload) соответствующего потока, а заголовки приходят отдельно.
  • Инструменты (DevTools/прокси/библиотеки) обычно показывают это как «Headers» и «Response/Body», скрывая детали фрейминга.

Типичные ловушки и проверки

Тело может отсутствовать полностью: например, для ответа на HEAD, а также для статусов 1xx, 204 и 304 содержимое тела не передаётся.

Следует различать «тело сообщения на линии» и «чистый контент»: при Transfer-Encoding: chunked данные идут чанками со служебными размерами, и читаемый HTML получается после удаления этой служебной обвязки.

Пример chunked-ответа (HTML находится внутри чанков):

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked

1a
<!doctype html><html><body>
10
Hello, world!
0

Мини-проверка «где HTML» (алгоритм рассуждения):

  1. Проверяется метод и статус: если HEAD или 204/304 — тела не будет.
  2. Находится граница headers/body (в HTTP/1.1 это \r\n\r\n).
  3. Проверяется Content-Type: если text/html, то содержимое тела является HTML-представлением.
  4. Проверяется Content-Encoding: при наличии выполняется декодирование перед анализом содержимого.
  5. Проверяется Transfer-Encoding: при chunked учитывается служебная разметка чанков, если анализ идёт по «сырому» потоку.

Кратко: HTML находится в body/content HTTP-ответа после заголовков (в HTTP/1.1 — после \r\n\r\n); Content-Type определяет интерпретацию как HTML, а сжатие и chunked-передача могут скрывать «читаемый» HTML до декодирования.