diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..dcfbbbb --- /dev/null +++ b/app/main.py @@ -0,0 +1,50 @@ +import logging +from contextlib import asynccontextmanager +from typing import AsyncIterator + +from fastapi import FastAPI, HTTPException, Request +from fastapi.exceptions import RequestValidationError +from fastapi.responses import JSONResponse + +from app.api import router +from app.checker import EndpointChecker +from app.settings import Settings, get_settings +from app.store import MonitorStore + + +def configure_logging(level: str) -> None: + logging.basicConfig(level=level.upper(), format="%(message)s") + + +def create_app(settings: Settings | None = None) -> FastAPI: + config = settings or get_settings() + + @asynccontextmanager + async def lifespan(application: FastAPI) -> AsyncIterator[None]: + configure_logging(config.log_level) + application.state.store = MonitorStore() + application.state.checker = EndpointChecker(config) + yield + + application = FastAPI(title="Endpoint Monitor", version="1.0.0", lifespan=lifespan) + application.include_router(router) + + @application.exception_handler(HTTPException) + async def http_error(_request: Request, exc: HTTPException) -> JSONResponse: + if isinstance(exc.detail, tuple): + code, message = exc.detail + else: + code, message = "http_error", str(exc.detail) + return JSONResponse(status_code=exc.status_code, + content={"error": {"code": code, "message": message}}, + headers=exc.headers) + + @application.exception_handler(RequestValidationError) + async def validation_error(_request: Request, _exc: RequestValidationError) -> JSONResponse: + return JSONResponse(status_code=422, content={"error": { + "code": "validation_error", "message": "Request validation failed"}}) + + return application + + +app = create_app()