api_key.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  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. t0 = time.time()
  15. if path == "/health":
  16. response = await call_next(request)
  17. return response
  18. logger.info("--> %s %s (client=%s)", method, path, client_ip)
  19. if settings.api_auth_enabled and path != "/health":
  20. header_value = request.headers.get(settings.api_auth_header_name, "")
  21. prefix = settings.api_auth_prefix
  22. if prefix and header_value.startswith(prefix + " "):
  23. token = header_value[len(prefix) + 1:]
  24. else:
  25. token = header_value
  26. if token not in settings.api_auth_keys:
  27. elapsed = time.time() - t0
  28. logger.warning("<-- %s %s 401 Unauthorized (%.3fs, client=%s)",
  29. method, path, elapsed, client_ip)
  30. return JSONResponse(
  31. status_code=401,
  32. content={"error": settings.api_auth_error_message},
  33. )
  34. response = await call_next(request)
  35. elapsed = time.time() - t0
  36. logger.info("<-- %s %s %d (%.3fs)", method, path, response.status_code, elapsed)
  37. return response