Обработка запросов и ответов

В Express объект req (IncomingMessage) содержит данные HTTP-запроса, объект res (ServerResponse) — инструменты для формирования и отправки ответа клиенту.

Зачем нужно

Понимание API req и res — основа разработки на Express. Именно через эти объекты извлекаются параметры маршрута, тело запроса, заголовки, куки; устанавливаются статус-коды, заголовки ответа, отправляются данные. Без этого невозможно написать ни один обработчик.

Где используется

  • Каждый обработчик маршрута в Express
  • Middleware для модификации запроса/ответа
  • Логирование, метрики, трассировка

Основной контент

Объект req — входящий запрос

app.get('/api/users/:id', (req, res) => {
  // URL и метод
  console.log(req.method);      // 'GET'
  console.log(req.path);        // '/api/users/42'
  console.log(req.originalUrl); // '/api/users/42?include=posts'
  console.log(req.hostname);    // 'api.example.com'
  console.log(req.protocol);    // 'https'
  console.log(req.ip);          // '192.168.1.1'

  // Параметры маршрута
  console.log(req.params.id);   // '42'

  // Query string: GET /users?page=2&limit=10
  console.log(req.query.page);  // '2'
  console.log(req.query.limit); // '10'

  // Тело запроса (требует express.json())
  console.log(req.body);        // { name: 'Alice', email: '...' }

  // Заголовки
  console.log(req.headers);
  console.log(req.get('Authorization')); // 'Bearer token...'
  console.log(req.get('Content-Type'));  // 'application/json'

  // Куки (требует cookie-parser)
  console.log(req.cookies.sessionId);

  // Данные от middleware (добавляются в req)
  console.log(req.user);    // добавлен auth middleware
  console.log(req.file);    // добавлен Multer
});

Объект res — ответ

app.get('/demo', (req, res) => {
  // Статус-код (всегда устанавливать до отправки)
  res.status(200);

  // Отправить JSON
  res.json({ message: 'ok', data:  });

  // Отправить текст
  res.send('Hello, World!');

  // Отправить файл
  res.sendFile(path.join(__dirname, 'public', 'index.html'));

  // Редирект
  res.redirect(301, 'https://new-url.com');
  res.redirect('/login');

  // Скачать файл
  res.download('/path/to/report.pdf', 'report.pdf');

  // Render шаблон (EJS, Pug)
  res.render('index', { title: 'Home', user: req.user });

  // Установить заголовок
  res.setHeader('X-Custom-Header', 'value');
  res.set('Cache-Control', 'no-cache');

  // 204 No Content (нет тела)
  res.status(204).send;

  // Конец без данных
  res.end();
});

Цепочка вызовов

res
  .status(201)
  .set('X-Created-Id', String(user.id))
  .json({ data: user, message: 'Created' });

Content-Type

// json устанавливает Content-Type: application/json автоматически
res.json({ ok: true });

// send определяет тип по данным
res.send('text');       // text/html
res.send(Buffer.from('...'));  // application/octet-stream

// Явная установка
res.type('application/pdf');
res.type('json');  // сокращение

Стриминг ответа

const fs = require('fs');

app.get('/video', (req, res) => {
  res.setHeader('Content-Type', 'video/mp4');
  fs.createReadStream('video.mp4').pipe(res);
});

Middleware модифицирует req

// auth middleware добавляет req.user
async function authMiddleware(req, res, next) {
  const token = req.get('Authorization')?.replace('Bearer ', '');
  if (!token) return res.status(401).json({ error: 'Unauthorized' });

  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next;
  } catch {
    res.status(401).json({ error: 'Invalid token' });
  }
}

Частые ошибки

  • Отправить ответ дваждыres.json после res.send: "Cannot set headers after they are sent"
  • Не установить статус до данныхres.status(404).json(...) — правильно; res.json(...).status(404) — нет
  • req.body == undefined — не подключён express.json или express.urlencoded middleware
  • req.params.id — строка, не числоparseInt(req.params.id) или Number(req.params.id) обязательны при работе с числовыми ID

Связанные темы

Ресурсы