← Назад к вопросам

Приведи пример использования middleware

1.3 Junior🔥 231 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Middleware в Python: Примеры и Использование

Middleware — это промежуточный слой в приложении, который обрабатывает request и response. Давайте разберём разные примеры в контексте Django и других фреймворков.

1. Django Middleware

Что такое Django Middleware?

Middleware в Django — это класс, который имеет методы для обработки request/response на разных этапах:

# Структура middleware
class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # Код ПЕРЕД обработкой request
        
        response = self.get_response(request)  # Вызов следующего middleware или view
        
        # Код ПОСЛЕ обработки request
        
        return response

Пример 1: Логирование всех запросов

# middleware.py
import logging
from django.utils.deprecation import MiddlewareMixin

logger = logging.getLogger(__name__)

class RequestLoggingMiddleware(MiddlewareMixin):
    """Middleware для логирования всех HTTP запросов"""
    
    def process_request(self, request):
        # Логируем информацию о request
        logger.info(f"{request.method} {request.path}")
        logger.info(f"GET params: {dict(request.GET)}")
        logger.info(f"POST params: {dict(request.POST)}")
        logger.info(f"User: {request.user}")
    
    def process_response(self, request, response):
        # Логируем status code
        logger.info(f"Response status: {response.status_code}")
        return response

Пример 2: Добавление заголовков безопасности

class SecurityHeadersMiddleware(MiddlewareMixin):
    """Добавляет заголовки безопасности к каждому ответу"""
    
    def process_response(self, request, response):
        # Защита от XSS
        response['X-Content-Type-Options'] = 'nosniff'
        response['X-Frame-Options'] = 'DENY'
        response['X-XSS-Protection'] = '1; mode=block'
        
        # HTTPS only
        response['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
        
        # CSP (Content Security Policy)
        response['Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline'"
        
        return response

Пример 3: Аутентификация и авторизация

from django.http import HttpResponseForbidden
from django.conf import settings

class AuthenticationMiddleware(MiddlewareMixin):
    """Проверяет, авторизован ли пользователь для определённых URL"""
    
    # Публичные URL, которые не требуют аутентификации
    PUBLIC_URLS = ['/login/', '/register/', '/api/public/']
    
    def process_request(self, request):
        # Если URL публичный, пропускаем проверку
        if any(request.path.startswith(url) for url in self.PUBLIC_URLS):
            return None
        
        # Если пользователь не авторизован
        if not request.user.is_authenticated:
            from django.shortcuts import redirect
            return redirect('login')
        
        return None

Пример 4: Кэширование ответов

from django.core.cache import cache
import hashlib

class CachingMiddleware(MiddlewareMixin):
    """Кэширует GET запросы"""
    
    def process_request(self, request):
        # Кэшируем только GET запросы
        if request.method != 'GET':
            return None
        
        # Создаём уникальный ключ для кэша
        cache_key = f"page:{request.path}:{request.GET.urlencode()}"
        
        # Пытаемся получить из кэша
        cached_response = cache.get(cache_key)
        if cached_response:
            return cached_response
        
        # Сохраняем ключ в request для использования в response middleware
        request._cache_key = cache_key
        return None
    
    def process_response(self, request, response):
        # Если в request есть cache_key, кэшируем ответ
        if hasattr(request, '_cache_key') and response.status_code == 200:
            cache.set(request._cache_key, response, timeout=3600)  # На 1 час
        
        return response

Пример 5: Обработка ошибок и исключений

import traceback
from django.http import JsonResponse
from django.views.debug import get_exception_reporter_filter

class ErrorHandlingMiddleware(MiddlewareMixin):
    """Обрабатывает необработанные исключения"""
    
    def process_exception(self, request, exception):
        # Логируем ошибку
        logger.error(f"Unhandled exception: {exception}")
        logger.error(traceback.format_exc())
        
        # В development показываем детали
        if settings.DEBUG:
            return None  # Показываем стандартный Django error page
        
        # В production отправляем JSON ошибку
        return JsonResponse({
            'error': 'Internal server error',
            'message': 'Something went wrong. Please try again later.'
        }, status=500)

2. FastAPI Middleware

Middleware в FastAPI

from fastapi import FastAPI, Request
import time
import logging

app = FastAPI()
logger = logging.getLogger(__name__)

# Пример 1: Логирование времени выполнения запроса
@app.middleware("http")
async def log_request_time(request: Request, call_next):
    start_time = time.time()
    
    # Выполняем запрос
    response = await call_next(request)
    
    # Вычисляем время
    process_time = time.time() - start_time
    logger.info(f"{request.method} {request.url.path} - {process_time:.3f}s")
    
    # Добавляем заголовок с временем выполнения
    response.headers["X-Process-Time"] = str(process_time)
    
    return response

# Пример 2: Добавление correlation ID для отслеживания
@app.middleware("http")
async def add_correlation_id(request: Request, call_next):
    import uuid
    
    # Генерируем уникальный ID для этого запроса
    correlation_id = str(uuid.uuid4())
    
    # Добавляем в контекст запроса
    request.state.correlation_id = correlation_id
    
    # Выполняем запрос
    response = await call_next(request)
    
    # Добавляем ID в ответ
    response.headers["X-Correlation-ID"] = correlation_id
    
    return response

Пример 3: CORS Middleware

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com", "https://www.example.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)

# Или с переменной окружения
import os

allowed_origins = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000").split(",")

app.add_middleware(
    CORSMiddleware,
    allow_origins=allowed_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

3. ASGI Middleware

Пример: Custom ASGI Middleware для валидации токена

from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
import jwt

app = FastAPI()

class JWTMiddleware:
    """Middleware для проверки JWT токена"""
    
    def __init__(self, app):
        self.app = app
    
    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return
        
        # Получаем заголовок Authorization
        headers = dict(scope["headers"])
        auth_header = headers.get(b"authorization", b"").decode()
        
        # Проверяем формат
        if not auth_header.startswith("Bearer "):
            response = JSONResponse(
                {"detail": "Invalid authorization header"},
                status_code=401
            )
            await response(scope, receive, send)
            return
        
        # Извлекаем токен
        token = auth_header.split(" ")[1]
        
        # Проверяем токен
        try:
            payload = jwt.decode(token, "secret", algorithms=["HS256"])
            scope["user"] = payload
        except jwt.InvalidTokenError:
            response = JSONResponse(
                {"detail": "Invalid token"},
                status_code=401
            )
            await response(scope, receive, send)
            return
        
        # Передаём дальше
        await self.app(scope, receive, send)

app.add_middleware(JWTMiddleware)

4. Регистрация Middleware в Django

# settings.py

MIDDLEWARE = [
    # Django встроенный middleware
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    
    # Ваш кастомный middleware
    'myapp.middleware.RequestLoggingMiddleware',
    'myapp.middleware.SecurityHeadersMiddleware',
    'myapp.middleware.CachingMiddleware',
    'myapp.middleware.ErrorHandlingMiddleware',
]

5. Реальный практический пример: Полный middleware

# middleware.py
import logging
import time
from django.utils.deprecation import MiddlewareMixin
from django.http import JsonResponse
import json
from django.conf import settings

logger = logging.getLogger(__name__)

class ComprehensiveLoggingMiddleware(MiddlewareMixin):
    """
    Полный middleware для логирования, мониторинга и обработки ошибок
    """
    
    def process_request(self, request):
        # Сохраняем время начала
        request._start_time = time.time()
        
        # Логируем запрос
        logger.info(f"\n{'='*80}")
        logger.info(f"REQUEST: {request.method} {request.path}")
        logger.info(f"IP: {self.get_client_ip(request)}")
        logger.info(f"User: {request.user}")
        
        if request.method in ['POST', 'PUT', 'PATCH']:
            try:
                logger.info(f"Body: {request.body.decode()[:500]}")
            except:
                pass
    
    def process_response(self, request, response):
        # Вычисляем время выполнения
        if hasattr(request, '_start_time'):
            duration = time.time() - request._start_time
            logger.info(f"RESPONSE: {response.status_code} - {duration:.3f}s")
        
        logger.info(f"{'='*80}\n")
        
        return response
    
    def process_exception(self, request, exception):
        logger.error(f"EXCEPTION: {exception}")
        
        if settings.DEBUG:
            return None
        
        return JsonResponse(
            {'error': 'Internal server error'},
            status=500
        )
    
    @staticmethod
    def get_client_ip(request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            return x_forwarded_for.split(',')[0]
        return request.META.get('REMOTE_ADDR')

Резюме

Middleware используется для:

  • Логирования — отслеживание запросов и ошибок
  • Аутентификации — проверка прав доступа
  • Кэширования — улучшение производительности
  • Безопасности — добавление заголовков и проверок
  • Обработки ошибок — красивая обработка исключений
  • Мониторинга — измерение производительности
  • Трансформации данных — изменение request/response

Выбор middleware зависит от вашего фреймворка (Django, FastAPI, Flask), но принцип везде одинаков: перехватить запрос, обработать, и передать дальше.