| """FastAPI dependencies for the explicit runtime service boundary.""" |
|
|
| import secrets |
|
|
| from fastapi import Depends, HTTPException, Request |
| from loguru import logger |
|
|
| from free_claude_code.application.errors import UnknownProviderError |
| from free_claude_code.application.ports import ProviderPort, RequestRuntimeLease |
| from free_claude_code.config.provider_catalog import PROVIDER_CATALOG |
| from free_claude_code.config.settings import Settings |
|
|
| from .ports import ApiServices |
|
|
|
|
| def get_services(request: Request) -> ApiServices: |
| """Return the complete services supplied when the app was constructed.""" |
| return request.app.state.services |
|
|
|
|
| def get_settings(services: ApiServices = Depends(get_services)) -> Settings: |
| """Return the current request-runtime settings snapshot.""" |
| return services.requests.current_settings() |
|
|
|
|
| def resolve_provider( |
| provider_type: str, |
| *, |
| lease: RequestRuntimeLease, |
| ) -> ProviderPort: |
| """Resolve a provider through one retained generation.""" |
| should_log_init = not lease.is_provider_cached(provider_type) |
| try: |
| provider = lease.resolve_provider(provider_type) |
| except UnknownProviderError: |
| logger.error( |
| "Unknown provider_type: '{}'. Supported: {}", |
| provider_type, |
| ", ".join(f"'{key}'" for key in PROVIDER_CATALOG), |
| ) |
| raise |
| if should_log_init: |
| logger.info("Provider initialized: {}", provider_type) |
| return provider |
|
|
|
|
| def require_proxy_auth( |
| request: Request, |
| settings: Settings = Depends(get_settings), |
| ) -> None: |
| """Require the configured proxy token as HTTP bearer authorization.""" |
| anthropic_auth_token = settings.anthropic_auth_token.strip() |
| if not anthropic_auth_token: |
| return |
|
|
| authorization = request.headers.get("authorization") |
| if not authorization: |
| raise HTTPException( |
| status_code=401, |
| detail="Missing proxy authentication token", |
| ) |
|
|
| parts = authorization.strip().split(maxsplit=1) |
| if len(parts) != 2 or parts[0].casefold() != "bearer": |
| raise HTTPException( |
| status_code=401, |
| detail="Invalid proxy authentication token", |
| ) |
| token = parts[1].strip() |
|
|
| if not token or not secrets.compare_digest( |
| token.encode("utf-8"), |
| anthropic_auth_token.encode("utf-8"), |
| ): |
| raise HTTPException( |
| status_code=401, |
| detail="Invalid proxy authentication token", |
| ) |
|
|