from fastapi import Request, status from fastapi.responses import JSONResponse from slowapi import Limiter from slowapi.util import get_remote_address from slowapi.errors import RateLimitExceeded from app.core.config import settings import redis # Initialize Redis connection for rate limiting try: redis_client = redis.from_url(settings.REDIS_URL) redis_client.ping() # Test connection except Exception: # Fallback to in-memory storage if Redis is not available redis_client = None limiter = Limiter( key_func=get_remote_address, storage_uri=settings.REDIS_URL if redis_client else "memory://", default_limits=[f"{settings.RATE_LIMIT_REQUESTS}/{settings.RATE_LIMIT_WINDOW}second"] ) def custom_rate_limit_exceeded_handler(request: Request, exc: RateLimitExceeded): response = JSONResponse( status_code=status.HTTP_429_TOO_MANY_REQUESTS, content={ "error": "Rate limit exceeded", "message": f"Rate limit exceeded: {exc.detail}", "retry_after": str(exc.retry_after) if exc.retry_after else None } ) response.headers["Retry-After"] = str(exc.retry_after) if exc.retry_after else "60" return response