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

C чем из Python middleware схож по логике работы

2.0 Middle🔥 161 комментариев
#Django#FastAPI и Flask#Архитектура и паттерны

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

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

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

# Python Middleware и его аналогии

Middleware в Python-приложениях (особенно в Django и FastAPI) работает по логике, схожей с несколькими паттернами из стандартной Python. Рассмотрим основные аналогии.

1. Декораторы (Decorators)

Это самая прямая аналогия. Middleware оборачивает функцию, перехватывает данные, модифицирует их, и передаёт дальше.

# Декоратор
def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Вызов функции: {func.__name__}")
        result = func(*args, **kwargs)  # Вызов оригинальной функции
        print(f"Результат: {result}")
        return result
    return wrapper

@log_decorator
def add(a, b):
    return a + b

print(add(2, 3))
# Вывод:
# Вызов функции: add
# Результат: 5
# 5

# Middleware работает ровно так же, но на уровне HTTP запроса
# Структура идентична!

Сравнение Decorator vs Middleware

# ДЕКОРАТОР
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("До вызова")          # 1. Pre-processing
        result = func(*args, **kwargs)  # 2. Call original
        print("После вызова")       # 3. Post-processing
        return result
    return wrapper

@my_decorator
def business_logic():
    return "Result"

# MIDDLEWARE
def my_middleware(get_response):
    def middleware(request):
        print("До обработки запроса")      # 1. Pre-processing
        response = get_response(request)   # 2. Call view
        print("После обработки запроса")   # 3. Post-processing
        return response
    return middleware

# Логика 100% идентична!

2. Контекстные менеджеры (Context Managers)

Middleware похож на контекстный менеджер (with statement). Он подготавливает ресурсы, выполняет код, и очищает ресурсы.

# Контекстный менеджер
class DatabaseConnection:
    def __enter__(self):
        print("Подключение к БД")  # Setup
        self.conn = create_connection()
        return self.conn
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Отключение от БД")   # Cleanup
        self.conn.close()
        if exc_type:
            print(f"Произошла ошибка: {exc_val}")
        return False  # Не подавляем исключение

with DatabaseConnection() as conn:
    print("Выполняем запрос")      # Main logic
    conn.query("SELECT * FROM users")

# Вывод:
# Подключение к БД
# Выполняем запрос
# Отключение от БД

# Middleware делает то же самое:
class AuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # Setup (инициализация)
        print("Middleware инициализирован")
    
    def __call__(self, request):
        # Pre-processing (как __enter__)
        print("Проверка прав доступа")
        request.user = get_current_user(request)
        
        # Main logic (как код внутри with)
        response = self.get_response(request)
        
        # Post-processing (как __exit__)
        print("Логирование запроса")
        log_request(request, response)
        
        return response

3. Цепочка ответственности (Chain of Responsibility)

Middleware образует цепь, где каждый middleware передаёт запрос следующему.

# Паттерн Chain of Responsibility
class RequestHandler:
    def __init__(self, next_handler=None):
        self.next_handler = next_handler
    
    def handle(self, request):
        # Обработка
        request.data = process(request.data)
        
        if self.next_handler:
            return self.next_handler.handle(request)  # Передать дальше
        return request

# Собрать цепь
handler1 = RequestHandler(next_handler=None)
handler2 = RequestHandler(next_handler=handler1)
handler3 = RequestHandler(next_handler=handler2)

result = handler3.handle(request)

# Django Middleware работает ровно так же!
# Каждый middleware вызывает get_response, который указывает на следующий middleware

# Django middleware stack:
# Request -> Middleware1 -> Middleware2 -> Middleware3 -> View -> Middleware3 -> Middleware2 -> Middleware1 -> Response

4. Функции высшего порядка (Higher-Order Functions)

Middleware — это функция, которая принимает функцию и возвращает функцию.

# Функция высшего порядка
def apply_discount(discount_percent):
    def decorator(price_func):
        def wrapper(*args, **kwargs):
            original_price = price_func(*args, **kwargs)
            discounted = original_price * (1 - discount_percent / 100)
            return discounted
        return wrapper
    return decorator

@apply_discount(10)  # 10% скидка
def get_price():
    return 1000

print(get_price())  # 900

# Middleware (FastAPI) работает точно так же:
from fastapi import FastAPI, Request
from functools import wraps

app = FastAPI()

@app.middleware("http")
async def add_custom_header(request: Request, call_next):
    # call_next — это как price_func в примере выше
    # Это функция, которую нам нужно вызвать
    
    # Pre-processing
    request.state.request_id = generate_id()
    
    # Вызываем следующий middleware/view
    response = await call_next(request)
    
    # Post-processing
    response.headers["X-Request-ID"] = request.state.request_id
    
    return response

5. Pipeline паттерн

Middleware создаёт pipeline, где данные проходят через последовательность обработчиков.

# Pipeline паттерн
def pipeline(*functions):
    """Создаёт pipeline из функций"""
    def pipely(value):
        for func in functions:
            value = func(value)
        return value
    return pipely

# Функции для pipeline
def add_tax(price):
    return price * 1.2

def add_shipping(price):
    return price + 50

def apply_coupon(price):
    return price * 0.9

# Собрать pipeline
process_order = pipeline(add_tax, add_shipping, apply_coupon)
final_price = process_order(1000)
print(final_price)  # ((1000 * 1.2) + 50) * 0.9 = 1134

# Django/FastAPI Middleware работает по той же логике:
# Request -> Middleware1 -> Middleware2 -> Middleware3 -> View
#
# Каждый middleware — это функция в pipeline

Практическое сравнение

Django Middleware

class AuthenticationMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # Pre-processing
        token = request.META.get('HTTP_AUTHORIZATION')
        if token:
            request.user = authenticate_user(token)
        
        # Call next middleware/view
        response = self.get_response(request)
        
        # Post-processing
        response['X-User'] = request.user.username if request.user else 'anonymous'
        
        return response

# Это аналогично:
class AuthenticationDecorator:
    @staticmethod
    def authenticate(view_func):
        def wrapper(request):
            # Pre-processing
            token = request.META.get('HTTP_AUTHORIZATION')
            if token:
                request.user = authenticate_user(token)
            
            # Call view
            response = view_func(request)
            
            # Post-processing
            response['X-User'] = request.user.username if request.user else 'anonymous'
            
            return response
        return wrapper

FastAPI Middleware

@app.middleware("http")
async def log_requests(request: Request, call_next):
    import time
    
    # Pre-processing
    start_time = time.time()
    print(f"Request: {request.method} {request.url}")
    
    # Call next middleware/endpoint
    response = await call_next(request)
    
    # Post-processing
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(f"Response time: {process_time:.2f}s")
    
    return response

# Это аналогично функции высшего порядка:
def log_requests_decorator(func):
    async def wrapper(*args, **kwargs):
        import time
        start_time = time.time()
        print(f"Calling {func.__name__}")
        result = await func(*args, **kwargs)
        process_time = time.time() - start_time
        print(f"Execution time: {process_time:.2f}s")
        return result
    return wrapper

Заключение: основная аналогия

КонцепцияСходство с Middleware
Декоратор100% аналогично — оборачивает функцию, добавляет логику до/после
Контекстный менеджерSetup/Cleanup ресурсов — инициализация/завершение
Chain of ResponsibilityЦепь обработчиков, передача управления дальше
Функция высшего порядкаПринимает функцию, возвращает функцию
PipelineПоследовательная обработка данных через несколько функций

Главная сходство: Middleware — это функция, которая оборачивает другую функцию, добавляя функционал до и после её выполнения. Это достигается через декораторы или функции высшего порядка, которые передают управление следующему обработчику (через get_response в Django или call_next в FastAPI).

Таким образом, если вы понимаете, как работают декораторы в Python, вы поймёте и middleware — это одно и то же, просто на уровне HTTP запросов вместо отдельных функций.