fix: resolve duplicate header and improve Redis management
- Dashboard: Remove redundant header (Layout already provides it) - projectctl.sh: Add start_redis/stop_redis functions for automatic Redis lifecycle management on project start/stop - rate_limiter.py: Add fallback to memory storage when Redis unavailable 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ This module provides rate limiting functionality to protect against
|
||||
brute force attacks and DoS attempts on sensitive endpoints.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
from slowapi import Limiter
|
||||
@@ -12,10 +13,50 @@ from slowapi.util import get_remote_address
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
# Use memory storage for testing, Redis for production
|
||||
# This allows tests to run without a Redis connection
|
||||
_testing = os.environ.get("TESTING", "").lower() in ("true", "1", "yes")
|
||||
_storage_uri = "memory://" if _testing else settings.REDIS_URL
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_storage_uri() -> str:
|
||||
"""
|
||||
Determine the appropriate storage URI for rate limiting.
|
||||
|
||||
Priority:
|
||||
1. Use memory storage if TESTING environment variable is set
|
||||
2. Try Redis if available
|
||||
3. Fall back to memory storage if Redis is unavailable (with warning)
|
||||
|
||||
Note: Memory storage is acceptable for development but Redis should
|
||||
be used in production for consistent rate limiting across workers.
|
||||
"""
|
||||
# Use memory storage for testing
|
||||
testing = os.environ.get("TESTING", "").lower() in ("true", "1", "yes")
|
||||
if testing:
|
||||
return "memory://"
|
||||
|
||||
# Try to connect to Redis
|
||||
redis_url = settings.REDIS_URL
|
||||
try:
|
||||
import redis
|
||||
r = redis.Redis(
|
||||
host=settings.REDIS_HOST,
|
||||
port=settings.REDIS_PORT,
|
||||
db=settings.REDIS_DB,
|
||||
socket_connect_timeout=1,
|
||||
)
|
||||
r.ping()
|
||||
logger.info("Rate limiter using Redis storage")
|
||||
return redis_url
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Redis unavailable for rate limiting ({e}). "
|
||||
"Falling back to in-memory storage. "
|
||||
"Note: In production, Redis should be running for consistent "
|
||||
"rate limiting across multiple workers."
|
||||
)
|
||||
return "memory://"
|
||||
|
||||
|
||||
_storage_uri = _get_storage_uri()
|
||||
|
||||
# Create limiter instance with appropriate storage
|
||||
# Uses the client's remote address (IP) as the key for rate limiting
|
||||
|
||||
Reference in New Issue
Block a user