C чем из Python middleware схож по логике работы
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# 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 запросов вместо отдельных функций.