В Universal Router middleware играют ключевую роль в управлении маршрутизацией и обработке запросов. Они позволяют перехватывать маршруты, изменять контекст, выполнять асинхронные операции и управлять логикой перехода до того, как конкретный обработчик маршрута будет вызван. Важной особенностью является возможность применения middleware глобально, для всех маршрутов одновременно.
Глобальные middleware регистрируются при создании экземпляра роутера
или через метод router.use. Каждый middleware получает
контекст маршрута и функцию next, которая
позволяет передать управление следующему middleware или обработчику
маршрута.
Пример базовой структуры глобального middleware:
import UniversalRouter from 'universal-router';
const router = new UniversalRouter(routes, {
context: {},
resolveRoute(context, params) {
return context.route.action(context, params);
}
});
// Глобальное middleware
router.use(async (context, next) => {
console.log('Middleware выполнен перед маршрутом');
return next();
});
В данном примере console.log выполняется для каждого
запроса, а вызов next() гарантирует передачу управления
следующему элементу цепочки.
Universal Router поддерживает асинхронные функции в middleware, что позволяет использовать запросы к API, проверки авторизации или другие операции, требующие времени.
router.use(async (context, next) => {
const user = await fetchUserFromAPI(context.userId);
if (!user) {
return '/login'; // Перенаправление на другой маршрут
}
context.user = user;
return next();
});
Ключевой момент: middleware могут возвращать новый
маршрут или значение. Если возвращается значение, отличное от
next(), дальнейшее выполнение цепочки middleware может быть
остановлено, а роутер вернет это значение как результат
маршрутизации.
Порядок регистрации глобальных middleware важен, так как Universal Router выполняет их строго последовательно:
next().next(), выполнение следующих middleware прекращается.Пример последовательного выполнения:
router.use(async (context, next) => {
console.log('Первый middleware');
await next();
console.log('Первый middleware после next');
});
router.use(async (context, next) => {
console.log('Второй middleware');
await next();
console.log('Второй middleware после next');
});
Вывод в консоли будет следующим:
Первый middleware
Второй middleware
Второй middleware после next
Первый middleware после next
Такой порядок позволяет оборачивать обработку маршрута и выполнять действия до и после него.
Контекст (context) является объектом, который передается
всем middleware и обработчику маршрута. Глобальные middleware могут
изменять контекст для всех маршрутов:
router.use((context, next) => {
context.startTime = Date.now();
return next();
});
router.use(async (context, next) => {
await next();
console.log(`Маршрут выполнен за ${Date.now() - context.startTime} мс`);
});
Таким образом, можно реализовать логирование времени выполнения маршрутов, добавление общих данных и состояние, которое будет доступно в любом обработчике маршрута.
Глобальные middleware позволяют реализовать глобальные проверки и редиректы. Например, проверка авторизации:
router.use((context, next) => {
if (!context.user && context.path !== '/login') {
return '/login';
}
return next();
});
Если возвращается строка или объект маршрута, роутер выполнит автоматическое перенаправление. При этом последующие middleware для текущего маршрута могут быть пропущены.
Также можно обрабатывать ошибки централизованно:
router.use(async (context, next) => {
try {
return await next();
} catch (error) {
console.error('Произошла ошибка маршрутизации:', error);
return '/error';
}
});
Такой подход гарантирует, что любые исключения в маршрутах или других middleware не приведут к падению приложения.
Universal Router полностью поддерживает цепочки асинхронных
middleware, включая вложенные вызовы next(). Это позволяет
создавать сложные маршрутизаторы с многоуровневыми проверками и
промежуточной обработкой.
router.use(async (context, next) => {
console.log('Начало глобального middleware');
await someAsyncCheck();
const result = await next();
console.log('Конец глобального middleware');
return result;
});
Глобальные middleware могут комбинироваться с локальными middleware на уровне конкретного маршрута, создавая гибкую иерархию обработки.
Глобальные middleware в Universal Router обеспечивают мощный инструмент для управления маршрутизацией, позволяя контролировать поток данных, авторизацию и обработку ошибок, создавая основу для масштабируемых приложений на JavaScript.