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:
beabigegg
2026-01-07 21:53:16 +08:00
parent 4b5a9c1d0a
commit a7c452ffd8
3 changed files with 154 additions and 84 deletions

View File

@@ -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