Из чего состоит структура HTTP-запроса?

Ответ

HTTP-запрос, который обрабатывает Node.js-сервер, состоит из трёх основных частей:

1. Стартовая строка (Request Line): Содержит метод, путь запроса и версию протокола. GET /api/users?active=true HTTP/1.1

  • Метод: GET, POST, PUT, DELETE, PATCH и др.
  • Путь (Path): URL-адрес ресурса, часто с параметрами пути (например, /api/users/:id).
  • Версия протокола: Обычно HTTP/1.1 или HTTP/2.

2. Заголовки (Headers): Метаданные запроса в формате Ключ: Значение. В Node.js они доступны в объекте req.headers.

Host: example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
User-Agent: Mozilla/5.0
Accept: application/json

3. Тело запроса (Body): Необязательная часть, присутствует в POST, PUT, PATCH запросах. Содержит передаваемые данные (JSON, форма, файлы).

{
  "name": "Alice",
  "email": "alice@example.com"
}

Пример разбора в чистом Node.js:

const http = require('http');

const server = http.createServer((req, res) => {
  // 1. Стартовая строка
  const { method, url } = req;
  console.log(`[${method}] ${url}`);

  // 2. Заголовки
  console.log('Headers:', req.headers['content-type']);

  // 3. Тело (собирается по частям)
  let body = [];
  req.on('data', chunk => body.push(chunk));
  req.on('end', () => {
    body = Buffer.concat(body).toString();
    console.log('Body:', body);
    // Парсинг JSON, если заголовок верный
    if (req.headers['content-type'] === 'application/json') {
      const data = JSON.parse(body);
      console.log('Parsed data:', data);
    }
    res.end('OK');
  });
});

server.listen(3000, () => console.log('Сервер слушает порт 3000'));

В фреймворках типа Express эта структура абстрагирована: req.method, req.path, req.headers, req.body.

Ответ 18+ 🔞

Давай разберём, как эта штука под капотом работает, а то некоторые думают, что запрос — это просто волшебство. Представь, что твой сервер на Node.js — это такой вечно голодный зверь, а HTTP-запрос — это посылка с едой. И эту посылку нужно правильно распаковать, а то подавится.

1. Наклейка на коробке (Стартовая строка): Это самая важная бумажка. Там написано, что внутри и как с этим обращаться. GET /api/users?active=true HTTP/1.1

  • Метод (Что делать?): GET (посмотреть), POST (засунуть), PUT (поменять), DELETE (выкинуть) и прочие. Без метода — нихуя не понятно.
  • Путь (Где искать?): Адрес, куда эту посылку принести. Иногда с номером квартиры, типа /api/users/:id.
  • Версия протокола (На каком языке инструкция?): Обычно HTTP/1.1. Если HTTP/2 — значит, посылка приехала на крутой тачке, побыстрее.

2. Опись вложения (Заголовки): Целая пачка бумажек с уточнениями. В Node.js они все валяются в req.headers.

Host: example.com
Content-Type: application/json  // Внутри JSON, не открывай топором!
Authorization: Bearer eyJhbGciOiJIUzI1NiIs... // Ключ от квартиры, где деньги лежат
User-Agent: Mozilla/5.0 // Кто отправил (часто врут, пидарасы)
Accept: application/json // Хочу получить ответ в JSON, а не в зубы

Без этих заголовков — доверия ебать ноль. Пришла тебе посылка с надписью "рыба", а внутри кирпич. Вот и весь расклад.

3. Само вложение, блядь (Тело запроса): А вот и долгожданный контент! Лежит не во всех посылках, а только в тех, где что-то передают (POST, PUT). Может быть JSON'ом, формой или даже файлом.

{
  "name": "Alice",
  "email": "alice@example.com"
}

А теперь, ёпта, смотри как это всё в голом Node.js выглядит:

const http = require('http');

const server = http.createServer((req, res) => {
  // 1. Сначала читаем наклейку
  const { method, url } = req;
  console.log(`[${method}] ${url}`); // Например, [POST] /api/login

  // 2. Потом смотрим опись (заголовки)
  console.log('Что за тип контента?', req.headers['content-type']);

  // 3. А теперь самое интересное — распаковываем тело. Оно приходит кусками!
  let bodyChunks = [];
  req.on('data', chunk => bodyChunks.push(chunk)); // Собираем куски
  req.on('end', () => {
    // Все куски собрали, склеиваем в одну строку
    const rawBody = Buffer.concat(bodyChunks).toString();
    console.log('Сырое тело:', rawBody);

    // Если в описи было написано "application/json", пытаемся распарсить
    if (req.headers['content-type'] === 'application/json') {
      try {
        const data = JSON.parse(rawBody);
        console.log('Распарсенные данные:', data);
      } catch (e) {
        console.log('Ёпта, кривой JSON прислали!', e.message);
      }
    }
    res.end('OK, получил твою хуйню');
  });
});

server.listen(3000, () => console.log('Сервер охуел и слушает порт 3000'));

А в Express'е, конечно, всё это за тебя делают — там уже готовые req.method, req.path, req.headers и req.body. Но понимать, откуда ноги растут — это, чувак, обязательно, а то так и будешь манда с ушами, которая только готовыми решениями тыкает.