Files
awg-dash/backend/awg_api/app.py
T
embeddevio 83d5a23406
contract-openapi / openapi-contract (push) Has been cancelled
contract-openapi / ts-client-is-current (push) Has been cancelled
feat(api): мок-контрол-плейн по контракту + единый формат ошибок (Refs #19)
- app.py: create_app() собирает мок-сервер и отдаёт /openapi.json из спецификации.
- errors.py: ApiError + хендлеры, приводящие 4xx/5xx/422 к схеме Error.
- deps.py: Bearer-токен и cookie-сессия (ADR-008).
- schemas.py: pydantic-модели запросов, зеркалящие схемы контракта (extra=forbid,
  writeOnly для секретов).
2026-10-22 00:21:06 +03:00

48 lines
1.8 KiB
Python

"""Сборка FastAPI-приложения мок-контрол-плейна (контракт ``docs/openapi.yaml``)."""
from __future__ import annotations
import os
from typing import Any
from fastapi import FastAPI
from awg_api import __version__
from awg_api.contract import load_spec
from awg_api.errors import install_error_handlers
from awg_api.routers import auth, config, devices, ops, routing, status
from awg_api.state import DEV_TOKEN, MockState
from awg_api.ws import metrics
TOKEN_ENV_VAR = "AWG_API_TOKEN" # noqa: S105 — имя переменной окружения, не секрет
class ContractFastAPI(FastAPI):
"""FastAPI, отдающий ``/openapi.json`` из контрактной спецификации, не из кода."""
def openapi(self) -> dict[str, Any]:
return load_spec()
def create_app(state: MockState | None = None, token: str | None = None) -> FastAPI:
"""Создаёт приложение мок-сервера; ``state``/``token`` подменяются в тестах."""
resolved_token = token or os.environ.get(TOKEN_ENV_VAR) or DEV_TOKEN
mock_state = state if state is not None else MockState()
mock_state.token = resolved_token
app = ContractFastAPI(
title="awg-dash API",
version=__version__,
description="Мок-контрол-плейн по контракту docs/openapi.yaml (задача #19)",
)
app.state.mock_state = mock_state
app.state.api_token = resolved_token
install_error_handlers(app)
app.include_router(ops.router)
app.include_router(auth.router)
app.include_router(status.router)
app.include_router(config.router)
app.include_router(routing.router)
app.include_router(devices.router)
app.include_router(metrics.router)
return app