Обновлены пути к библиотекам в Dockerfile для соответствия новой версии Python. Исправлены все тесты, теперь все проходят
110 lines
3.7 KiB
Markdown
110 lines
3.7 KiB
Markdown
---
|
||
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()`** для локальной регистрации на уровне модуля
|