BrejBala's picture
final changes with API key
b09b8a3
import os
from functools import lru_cache
from typing import Optional
from fastapi import HTTPException, Security, status
from fastapi.security import APIKeyHeader
from app.core.logging import get_logger
logger = get_logger(__name__)
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
@lru_cache(maxsize=1)
def _get_configured_api_key() -> Optional[str]:
"""Return the configured API key, or None if not set.
The key is read from the API_KEY environment variable.
"""
raw = os.getenv("API_KEY")
if raw is None or not raw.strip():
return None
return raw.strip()
def _is_production_like() -> bool:
"""Heuristic to detect production / hosted environments.
- ENV=production
- or running on Hugging Face Spaces (SPACE_ID or HF_HOME set)
"""
env = os.getenv("ENV", "").strip().lower()
if env == "production":
return True
if os.getenv("SPACE_ID") or os.getenv("HF_HOME"):
return True
return False
def validate_api_key_configuration() -> None:
"""Validate API key configuration at startup.
Behaviour:
- In production-like environments (HF Spaces or ENV=production):
- API_KEY MUST be set, otherwise raise RuntimeError (fail fast).
- In other environments:
- If API_KEY is missing, allow running open but log a clear warning.
"""
configured = _get_configured_api_key()
if _is_production_like():
if not configured:
raise RuntimeError(
"API_KEY environment variable must be set when running in "
"production or on Hugging Face Spaces. Configure API_KEY in "
"your environment or Space secrets."
)
logger.info("API key configured for production / hosted environment.")
else:
if not configured:
logger.warning(
"API_KEY is not set; backend is running without authentication. "
"This is intended for local development only."
)
else:
logger.info("API key configured for development mode.")
async def require_api_key(api_key: Optional[str] = Security(api_key_header)) -> None:
"""FastAPI dependency that enforces X-API-Key when configured.
- If API_KEY is not configured (local/dev), this is a no-op.
- If API_KEY is configured:
- Missing or mismatched X-API-Key results in HTTP 403.
"""
configured = _get_configured_api_key()
if not configured:
# No API key configured: dev mode, do not enforce.
return
if not api_key:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Missing API key. Provide X-API-Key header.",
)
if api_key != configured:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid API key.",
)