Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Тело HTTP-запроса Протокол HTTP

HTTP request и response могут содержать так называемое тело (body).

Структура и тело запроса

Мы уже знаем, что сам HTTP запрос состоит из заголовков и опционального тела запроса. Для отделения заголовков от тела существуют определенные правила. Давайте посмотрим на примере, как работать с body и каким образом посылать какие-то данные кроме заголовков. Сделаем HTTP запрос к хосту hexlet.io:

telnet hexlet.io 80

GET / HTTP/1.1
Host: hexlet.io

HTTP/1.1 301 Moved Permanently
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Location: https://34.102.241.4/
Content-Length: 218
Date: Tue, 07 Jul 2020 03:50:16 GMT

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://34.102.241.4/">here</A>.
</BODY></HTML>

В ответ мы получаем какие-то заголовки и далее идёт тело, которое нас как раз и интересует. В данном случае это не какая-то страница нашего сайта, а просто страница, которую отдаёт сервер. Она связана с перенаправлением.

Если с заголовками всё понятно, они отделяются друг от друга переводом строки и для отправки мы добавляем еще один перевод, который выглядит как пустая строка. То как быть с телом запроса? Оно может содержать внутри всё что угодно. Мы не можем кодировать перевод строки как специальный символ. Ведь те самые два перевода строки могут находиться внутри тела запроса. Но существуют и другие причины, по которым в текстовом протоколе нельзя просто так определить когда заканчивается тело. Если бы мы приняли ответ при отсутствии каких-то специальных механизмов, то после того как сервер отправил первые два перевода строки мы сразу увидели бы ответ и всё что посылалось дальше вообще не считалось бы частью ответа HTTP response. Для решения этой проблемы был придуман другой, более универсальный механизм. Он основан на передаче специального заголовка.

Во время отправки ответа сервер формирует специальный заголовок, который называется Content-Length. Это и есть ключ к тому как работать с body. Перед тем как отправить тело ответа, происходит вычисление его длины и записывается количество байт.

# число — количество байт
Content-Length: 218

После того, как передан такой заголовок другая сторона будет ожидать ровно столько байт, сколько в нём указано. Как мы помним, для response и request это работает абсолютно одинаково. После того как был передан последний символ, соединение закрывается. Стоит уточнить, что закрывается именно HTTP-сессия. На сервере может быть активен keep-alive, но ключевой момент в том, что запрос считается завершённым и отображается.

Указание размера тела нужно не только для отправки ответа, но и при запросах, когда на сервер посылаются, например, данные формы.

Практика показывает, что не все серверы правильно работают при наличии только заголовка Content-Length. Им не хватает еще одного. Тип содержимого запроса или ответа, которое содержит body, должен быть как-то идентифицирован. По умолчанию в стандарте сказано, что сервер может сам попытаться определить содержимое контента на основе различных способов. Например, мы в query string делаем запрос image.png.

POST /image.png HTTP/1.1

Совсем не обязательно, но сервер может понять, что это картинка в формате png, и как-то это использовать. Во всех остальных случаях, когда сервер не может определить тип контента, он должен использовать заголовок Content-Type: application/octet-stream. Это означает, что в теле запроса передаётся просто поток байт. Хотя серверы должны работать именно так, но часто всё происходит по другому. Если указан только Content-Length, то сервер отказывается принимать данные. Он просто закрывает соединение после двух переводов строки, еще до body. Этот нюанс выяснен экспериментальным путём.

Еще одно замечание по поводу body. С точки зрения стандарта HTTP тело может присутствовать в любом запросе и никак не связано с глаголом. Посылать body можно в HEAD, POST, PUT и других запросах. Если мы посылаем body с GET, хотя это не описано в стандарте, сервер никак не будет на это реагировать, более того, он и не должен, так как с практической точки зрения это не имеет смысла. Также есть типы запросов, при которых он не будет посылать в ответ body ни в коем случае. Например, ответ на HEAD, когда мы запрашиваем только заголовки, так как такова семантика этого глагола. Еще тело не отправляется, когда мы получаем в ответ такие статусы как 204 — нет контента и некоторые другие.


Дополнительные материалы

  1. Википедия / Тело сообщения
  2. Формат HTTP-запросов
  3. Формат HTTP-ответов

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Фронтенд-разработчик
Профессия
Разработка фронтенд-компонентов веб-приложений
30 июня 10 месяцев
Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
30 июня 10 месяцев
Иконка программы PHP-разработчик
Профессия
Разработка веб-приложений на Laravel
30 июня 10 месяцев
Иконка программы Node.js-разработчик
Профессия
Разработка бэкенд-компонентов веб-приложений
30 июня 10 месяцев
Иконка программы Fullstack-разработчик
Профессия
Новый
Разработка фронтенд и бэкенд компонентов веб-приложений
30 июня 16 месяцев
Иконка программы Java-разработчик
Профессия
Разработка приложений на языке Java
30 июня 10 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»