Как в HTTP-запросе разделяются заголовки (headers) и тело (body)?

«Как в HTTP-запросе разделяются заголовки (headers) и тело (body)?» — вопрос из категории Сети, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В HTTP-запросе (и ответе) заголовки и тело разделяются двумя последовательными символами переноса строки (rnrn). Это пустая строка после последнего заголовка.

Структура сырого HTTP-запроса:

POST /api/user HTTP/1.1rn        <-- Стартовая строка
Host: example.comrn               <-- Заголовки (Headers)
Content-Type: application/jsonrn
{"name": "John"}                     <-- Тело (Body), после rnrn

Как работать с этим в PHP:

  1. Для входящих запросов: PHP делает это разделение автоматически.
    • Заголовки: Доступны через суперглобальный массив $_SERVER (с префиксом HTTP_) или функцию getallheaders().
    • Тело: Для POST-запросов с формами — в $_POST. Для сырых данных (JSON, XML) — через поток php://input.
// Получение всех заголовков запроса
$headers = getallheaders();

// Получение сырого тела запроса (например, для JSON)
$rawBody = file_get_contents('php://input');
$data = json_decode($rawBody, true);
  1. Для создания исходящих запросов (например, с помощью cURL): Нужно правильно сформировать строку запроса или использовать библиотеки, которые делают это за вас.
// Пример ручной сборки (упрощенно)
$requestData = "POST /endpoint HTTP/1.1rn";
$requestData .= "Host: api.example.comrn";
$requestData .= "Content-Type: application/jsonrn";
$requestData .= "Content-Length: " . strlen($body) . "rn";
$requestData .= "rn"; // Критически важная пустая строка
$requestData .= $body;