-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.py
More file actions
80 lines (61 loc) · 2.22 KB
/
api.py
File metadata and controls
80 lines (61 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import logging
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from .config import get_settings
from .main import main as run_main_logic
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncGenerator[None]:
"""
Lifecycle manager for the FastAPI app.
Startup and Shutdown logic goes here.
"""
# Startup logic
settings = get_settings()
logger.info(
"Starting %s in %s mode...", settings.PROJECT_NAME, settings.ENVIRONMENT
)
yield
# Shutdown logic
logger.info("Shutting down %s...", settings.PROJECT_NAME)
def create_app() -> FastAPI:
"""Factory function to create the FastAPI application."""
settings = get_settings()
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
lifespan=lifespan,
docs_url="/docs" if settings.DEBUG else None,
redoc_url="/redoc" if settings.DEBUG else None,
)
@app.exception_handler(Exception)
async def global_exception_handler(
request: Request, exc: Exception
) -> JSONResponse:
"""Global exception handler to return consistent JSON errors."""
logger.exception(
"Unhandled exception: %s", exc, extra={"path": request.url.path}
)
# Don't expose internal error details in production
error_detail = str(exc) if settings.DEBUG else "Internal Server Error"
return JSONResponse(
status_code=500,
content={"detail": "Internal Server Error", "error": error_detail},
)
@app.get("/health")
async def health_check() -> dict[str, str]:
"""Health check endpoint for probes."""
return {"status": "ok", "version": settings.VERSION}
@app.get("/")
async def root() -> dict[str, str]:
"""Root endpoint example."""
return {"message": f"Hello from {settings.PROJECT_NAME} API"}
@app.get("/run")
async def trigger_run() -> dict[str, str]:
"""Trigger the main logic via API."""
run_main_logic()
return {"status": "Main logic executed"}
return app
app = create_app()