Files
web/backend/services/shared/inter_service_rate_limit.py
T

52 lines
1.6 KiB
Python

"""
Per-IP rate limits for internal FastAPI apps (messaging, file_storage).
Complements the main service's endpoint-specific limits. Uses a generous default
because traffic is mostly from the main backend (single Docker bridge IP).
"""
from __future__ import annotations
from fastapi import FastAPI, Request
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
from slowapi.util import get_remote_address
def _client_ip_key(request: Request) -> str:
if request is None:
return "unknown"
headers = request.headers
real = (headers.get("x-real-ip") or headers.get("X-Real-IP") or "").strip()
if real:
return real
forwarded = headers.get("x-forwarded-for") or headers.get("X-Forwarded-For")
if forwarded:
first = forwarded.split(",")[0].strip()
if first:
return first
if request.client and request.client.host:
return request.client.host
return get_remote_address(request)
def attach_internal_service_rate_limit(
app: FastAPI,
*,
default_limit: str = "6000/minute",
) -> Limiter:
"""
Register SlowAPI on ``app`` with a default limit for all routes.
Use ``@limiter.exempt`` on ``/health`` (and similar) so probes are not throttled.
"""
limiter = Limiter(
key_func=_client_ip_key,
default_limits=[default_limit],
storage_uri="memory://",
)
app.state.limiter = limiter
app.add_middleware(SlowAPIMiddleware)
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
return limiter