OmniVoice-Studio / backend /api /dependencies.py
Lê Phi Nam
Fix 403 loopback gate and HF_HOME writable cache error
0e56bd7
Raw
History Blame Contribute Delete
1.75 kB
"""
Shared FastAPI dependencies.
These are intentionally tiny — one concern per dependency — so they can be
composed at the route or router level without surprises.
Currently exposed:
- `require_loopback`: 403 unless the request came from a loopback origin.
"""
import os
from fastapi import HTTPException, Request
# IPv4 + IPv6 loopback literals + the conventional `localhost` hostname.
# `request.client.host` carries an address, not a hostname, so the literal
# "localhost" entry is defensive — some upstream wrappers (TestClient with
# a custom client tuple, certain reverse-proxy headers) may pass strings
# rather than parsed addresses. We accept the broader set without weakening
# the guard: nothing here matches a non-loopback origin.
_LOOPBACK_HOSTS = frozenset({"127.0.0.1", "::1", "localhost"})
_IS_PUBLIC = os.environ.get("OMNIVOICE_BIND_HOST") == "0.0.0.0"
def require_loopback(request: Request) -> None:
"""Reject any request whose `client.host` is not a loopback address.
Use as a router-level dependency to protect every route on the router
in one place:
router = APIRouter(dependencies=[Depends(require_loopback)])
Or as a per-route dependency for narrower scope:
@router.post("/foo", dependencies=[Depends(require_loopback)])
Returns None on success (FastAPI dependency convention). Raises 403
on rejection — the response body is `{"detail": "loopback origin required"}`
so existing tests for `/system/set-env` keep passing without modification.
"""
if _IS_PUBLIC:
return
host = request.client.host if request.client else None
if host not in _LOOPBACK_HOSTS:
raise HTTPException(status_code=403, detail="loopback origin required")