--- description: "Паттерны создания и использования middleware в aiogram" globs: ["helper_bot/middlewares/**/*.py"] --- # Паттерны Middleware ## Структура Middleware Все middleware наследуются от `aiogram.BaseMiddleware`: ```python from typing import Any, Dict from aiogram import BaseMiddleware from aiogram.types import TelegramObject class CustomMiddleware(BaseMiddleware): """Описание middleware.""" async def __call__( self, handler: Callable, event: TelegramObject, data: Dict[str, Any] ) -> Any: # Логика до обработки handler ... # Вызов следующего handler в цепочке result = await handler(event, data) # Логика после обработки handler ... return result ``` ## Порядок регистрации Middleware В `main.py` middleware регистрируются в следующем порядке (важно!): ```python # 1. DependenciesMiddleware - внедрение зависимостей dp.update.outer_middleware(DependenciesMiddleware()) # 2. MetricsMiddleware - сбор метрик dp.update.outer_middleware(MetricsMiddleware()) # 3. BlacklistMiddleware - проверка черного списка dp.update.outer_middleware(BlacklistMiddleware()) # 4. RateLimitMiddleware - ограничение частоты запросов dp.update.outer_middleware(RateLimitMiddleware()) ``` ## DependenciesMiddleware Внедряет глобальные зависимости во все handlers: ```python class DependenciesMiddleware(BaseMiddleware): async def __call__(self, handler, event: TelegramObject, data: Dict[str, Any]) -> Any: bdf = get_global_instance() # Внедрение зависимостей if 'bot_db' not in data: data['bot_db'] = bdf.get_db() if 'settings' not in data: data['settings'] = bdf.settings return await handler(event, data) ``` ## Обработка ошибок в Middleware ```python class CustomMiddleware(BaseMiddleware): async def __call__(self, handler, event, data): try: # Предобработка ... result = await handler(event, data) # Постобработка ... return result except Exception as e: # Обработка ошибок logger.error(f"Ошибка в middleware: {e}") # Решаем: пробрасывать дальше или обработать raise ``` ## Регистрация на уровне Router Middleware можно регистрировать на уровне конкретного router: ```python router = Router() router.message.middleware(SomeMiddleware()) # Только для message handlers router.callback_query.middleware(SomeMiddleware()) # Только для callback handlers ``` ## Best Practices 1. **Регистрируйте middleware в правильном порядке** - зависимости должны быть первыми 2. **Не изменяйте event** напрямую, используйте `data` для передачи информации 3. **Обрабатывайте ошибки** в middleware, но не глотайте их без логирования 4. **Используйте `outer_middleware`** для глобальной регистрации 5. **Используйте `router.middleware()`** для локальной регистрации на уровне модуля