support-bot-saas/backend/app/middleware.py
ed0ss 0063df0a87
Some checks are pending
CI / lint-backend (push) Waiting to run
CI / lint-frontend (push) Waiting to run
CI / build-backend (push) Blocked by required conditions
CI / build-frontend (push) Blocked by required conditions
Реструктуризация проекта в SaaS: FastAPI бэкенд, React SPA фронтенд, Helm-чарт, CI/CD
- Бэкенд: FastAPI + SQLAlchemy async + PostgreSQL, JWT-аутентификация,
  Qdrant multi-tenant векторное хранилище, Celery воркер
- Фронтенд: React + Vite + TypeScript SPA (логин, регистрация,
  дашборд, поиск по коллекциям, настройки)
- Инфраструктура: docker-compose, Helm-чарт, GitHub Actions CI,
  Prometheus/Grafana мониторинг
- Embedding через OpenRouter (nvidia/llama-nemotron-embed-vl-1b-v2:free)
- LLM: google/gemma-4-31b-it:free через OpenRouter
2026-06-20 17:40:27 +03:00

29 lines
1.1 KiB
Python

import time
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
from collections import defaultdict
class RateLimitMiddleware(BaseHTTPMiddleware):
def __init__(self, app, requests_per_minute: int = 10):
super().__init__(app)
self.requests_per_minute = requests_per_minute
self.requests: dict = defaultdict(list)
async def dispatch(self, request: Request, call_next):
if request.url.path.startswith("/api/health"):
return await call_next(request)
user_key = request.headers.get("X-Forwarded-For", request.client.host if request.client else "unknown")
now = time.time()
window = now - 60
self.requests[user_key] = [t for t in self.requests[user_key] if t > window]
self.requests[user_key].append(now)
if len(self.requests[user_key]) > self.requests_per_minute:
return JSONResponse(status_code=429, content={"detail": "Rate limit exceeded"})
return await call_next(request)