Проверяет понимание типовой организации бэкенд-стека: роутинг, валидация, авторизация, обработка ошибок и логирование.
Типичный бэкенд-стек организован по принципу разделения ответственности. Запрос проходит через несколько слоёв: сначала маршрутизация определяет, какой обработчик вызовется, затем middleware выполняет предварительные проверки (валидация, авторизация), далее бизнес-логика обрабатывает данные, и наконец ответ формируется с учётом ошибок и логирования.
Роутинг связывает URL и HTTP-методы с конкретными функциями. В Express это выглядит так:
app.get('/users', authMiddleware, validateQuery, (req, res) => {
// обработчик
});Маршруты группируются по ресурсам, что упрощает навигацию по коду.
Валидация проверяет входные данные до попадания в бизнес-логику. Используются библиотеки типа Joi или express-validator. Пример:
const schema = Joi.object({ email: Joi.string().email().required() });
app.post('/login', (req, res, next) => {
const { error } = schema.validate(req.body);
if (error) return res.status(400).json({ error: error.message });
next();
});Это предотвращает некорректные запросы и защищает от атак.
Авторизация проверяет права пользователя. Обычно используется JWT или сессии. Middleware проверяет токен и добавляет данные пользователя в запрос:
function auth(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
req.user = jwt.verify(token, SECRET);
next();
} catch { res.status(403).json({ error: 'Invalid token' }); }
}Централизованный обработчик ошибок перехватывает исключения и возвращает единообразный ответ. В Express это middleware с четырьмя аргументами:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({ error: err.message });
});Это гарантирует, что клиент всегда получит понятный ответ, а сервер не упадёт.
Логирование фиксирует запросы, ошибки и важные события. Используются библиотеки типа Winston или Morgan. Пример:
const logger = winston.createLogger({ transports: [new winston.transports.File({ filename: 'app.log' })] });
app.use(morgan('combined', { stream: { write: msg => logger.info(msg) } }));Логи помогают отлаживать и мониторить приложение.
Такая организация делает код предсказуемым, легко тестируемым и масштабируемым. Применяется в большинстве production-проектов, так как разделяет сквозные задачи и упрощает командную разработку.