Express.jsJuniorTechnical

Что такое middleware в Express.js? Объясните цикл запрос-ответ (request-response cycle).

Middleware — функция (req, res, next), встраиваемая в цепочку обработки запроса. Цикл запрос–ответ: клиент -> Node.js -> цепочка middleware -> роут-обработчик -> res.send() -> клиент.

Что такое middleware в Express.js

Middleware — функция с сигнатурой (req, res, next), которая получает объекты запроса и ответа, выполняет некоторую логику и либо завершает цикл запрос–ответ, либо передаёт управление следующей функции в цепочке через вызов next().

Цикл запрос–ответ

Когда клиент отправляет HTTP-запрос, Node.js получает его и передаёт Express. Express ищет совпадение по методу и пути, затем последовательно вызывает все подходящие middleware и роут-обработчики. Цикл завершается, когда один из обработчиков вызывает метод ответа (res.send(), res.json(), res.end()) или когда истекает тайм-аут соединения.

import express from 'express';

const app = express();

// 1. Парсинг тела запроса (встроенный middleware)
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 2. Пользовательский middleware — логирование
app.use((req, res, next) => {
  const start = Date.now();
  console.log(`--> ${req.method} ${req.url}`);

  // Перехватываем момент отправки ответа
  res.on('finish', () => {
    const ms = Date.now() - start;
    console.log(`<-- ${res.statusCode} ${ms}ms`);
  });

  next(); // передаём управление дальше
});

// 3. Middleware аутентификации
app.use((req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Token required' });
  }
  req.user = { id: 42, token }; // обогащаем объект запроса
  next();
});

// 4. Роут-обработчик — конец цикла
app.get('/profile', (req, res) => {
  res.json({ userId: req.user.id });
});

// 5. Обработчик ошибок (4 параметра)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: err.message });
});

app.listen(3000);

Порядок выполнения

Middleware выполняются строго в том порядке, в котором они зарегистрированы через app.use() или app.METHOD(). Express проходит по ним как по стеку: если next() не вызван, цепочка останавливается на текущей функции.

Виды middleware

  • Встроенные: express.json(), express.static(), express.urlencoded().
  • Сторонние: cors, helmet, morgan, multer.
  • Пользовательские: любые функции (req, res, next), написанные разработчиком.
  • Обработчики ошибок: функции с четырьмя параметрами (err, req, res, next).

Подводные камни

  • Забытый next() — если не вызвать next() и не отправить ответ, запрос зависнет и клиент получит тайм-аут.
  • Порядок регистрации критичен — middleware, зарегистрированный после роута, не выполнится для этого роута.
  • Двойной ответ — вызов res.json() и затем next() приведёт к ошибке «headers already sent».
  • Async middleware без try/catch — необработанный rejected promise в async middleware не попадёт в обработчик ошибок Express (до версии 5.x нужно явно вызывать next(err)).
  • Порядок body-парсеровexpress.json() должен быть зарегистрирован до роутов, которые читают req.body.
  • Слишком широкий app.use('/') — перехватывает все запросы; нужно явно указывать пути или монтировать middleware на конкретные роутеры.

Common mistakes

  • Дает общий ответ про Node.js и не называет конкретные API Express.js.
  • Не объясняет, где в lifecycle находится middleware и request-response cycle.
  • Не разделяет validation, authorization, business logic и persistence.
  • Игнорирует ошибки, лимиты входных данных, observability и тестирование.

What the interviewer is testing

  • Может объяснить middleware и request-response cycle на примере кода.
  • Называет ключевые API: app.use(), next().
  • Использует точные API Express.js, а не вымышленные hooks/decorators/methods.
  • Видит production-риски: безопасность, отказоустойчивость, логирование и тесты.

Sources

Related topics