Что такое 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-риски: безопасность, отказоустойчивость, логирование и тесты.