В библиотеке Universal Router маршрутизация строится на основе маршрутов, определяемых в виде объектов с набором свойств. Одним из ключевых инструментов управления обработкой запроса является использование middleware на уровне маршрута. Middleware позволяет вставлять промежуточные шаги между определением маршрута и его финальной обработкой, предоставляя возможность изменять поведение маршрутов динамически.
Маршрут в Universal Router представляет собой объект с ключевыми полями:
{
path: '/example',
action: async (context, params) => { ... },
children: [...],
middleware: [...]
}
/user/:id).Каждый middleware получает объект context и объект
params, аналогично action, и может возвращать результат
либо передавать управление следующему middleware через
next().
Middleware — это функция, которая принимает три аргумента:
async function middleware(context, params, next) {
// Логика middleware
return next(); // Передача управления следующему middleware или action
}
const routes = [
{
path: '/admin',
middleware: [
async (context, params, next) => {
if (!context.user || !context.user.isAdmin) {
return '/login';
}
return next();
}
],
action: async (context) => {
return 'Admin dashboard';
}
}
];
В этом примере middleware проверяет, является ли пользователь
администратором. Если проверка не проходит, происходит редирект на
страницу /login. Если проверка успешна, управление
передаётся action маршрута.
Middleware можно определять на любом уровне вложенности маршрутов. При этом порядок выполнения следующий:
Пример:
const routes = [
{
path: '/user',
middleware: [
async (ctx, params, next) => {
console.log('User middleware');
return next();
}
],
children: [
{
path: '/:id',
middleware: [
async (ctx, params, next) => {
console.log('User ID middleware', params.id);
return next();
}
],
action: async (ctx, params) => `User profile ${params.id}`
}
]
}
];
Запрос к /user/42 вызовет:
User middlewareUser ID middleware 42User profile 42Universal Router полностью поддерживает асинхронные функции:
async function authMiddleware(context, params, next) {
const authorized = await checkUserAuth(context.user);
if (!authorized) return '/login';
return next();
}
Асинхронные операции, такие как запросы к API или базе данных, могут безопасно выполняться до вызова action маршрута.
Middleware может модифицировать объект context, добавляя новые свойства, которые будут доступны следующим middleware и action:
async function addTimestamp(context, params, next) {
context.timestamp = Date.now();
return next();
}
async function showTimestamp(context) {
return `Timestamp: ${context.timestamp}`;
}
Если middleware выбрасывает исключение, роутер передаст его наружу. Для обработки ошибок можно использовать глобальные middleware или оборачивать middleware в try/catch:
async function safeMiddleware(context, params, next) {
try {
return await next();
} catch (err) {
console.error('Middleware error', err);
return '/error';
}
}
Middleware может возвращать строку URL, объект с
redirect, либо промис:
async function redirectIfNotLogged(context, params, next) {
if (!context.user) return '/login';
return next();
}
При возврате URL роутер автоматически перенаправляет пользователя.
next() в middleware, если требуется
продолжение цепочки.Middleware на уровне маршрута в Universal Router предоставляет мощный инструмент контроля над маршрутизацией, позволяя внедрять проверку, модификацию данных и асинхронную обработку до вызова основной логики маршрута. Такой подход обеспечивает гибкость и модульность при построении сложных приложений.