api_key.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import logging
  2. import time
  3. from typing import Callable
  4. from fastapi import Request, Response
  5. from fastapi.responses import JSONResponse
  6. from starlette.middleware.base import BaseHTTPMiddleware
  7. from app.config import settings
  8. logger = logging.getLogger(__name__)
  9. class ApiKeyMiddleware(BaseHTTPMiddleware):
  10. async def dispatch(self, request: Request, call_next: Callable) -> Response:
  11. method = request.method
  12. path = request.url.path
  13. client_ip = request.client.host if request.client else "unknown"
  14. logger.info("--> %s %s (client=%s)", method, path, client_ip)
  15. t0 = time.time()
  16. if settings.api_auth_enabled and path != "/health":
  17. header_value = request.headers.get(settings.api_auth_header_name, "")
  18. prefix = settings.api_auth_prefix
  19. if prefix and header_value.startswith(prefix + " "):
  20. token = header_value[len(prefix) + 1:]
  21. else:
  22. token = header_value
  23. if token not in settings.api_auth_keys:
  24. elapsed = time.time() - t0
  25. logger.warning("<-- %s %s 401 Unauthorized (%.3fs, client=%s)",
  26. method, path, elapsed, client_ip)
  27. return JSONResponse(
  28. status_code=401,
  29. content={"error": settings.api_auth_error_message},
  30. )
  31. response = await call_next(request)
  32. elapsed = time.time() - t0
  33. logger.info("<-- %s %s %d (%.3fs)", method, path, response.status_code, elapsed)
  34. return response