101 lines
3.4 KiB
Python
101 lines
3.4 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import FastAPI, HTTPException, Request
|
|
from fastapi.exceptions import RequestValidationError
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app.api.routes import analysis, areas, datasets, demo, detection, exports, external, health, jobs, projects, qa, quality_checks, segmentation
|
|
from app.core.config import get_settings
|
|
from app.core.errors import AppError
|
|
from app.core.logging import configure_logging
|
|
|
|
|
|
def _to_error_payload(code: str, message: str, details: dict | list | None = None) -> dict:
|
|
return {
|
|
"error": {
|
|
"code": code,
|
|
"message": message,
|
|
"details": details or {},
|
|
},
|
|
}
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
settings = get_settings()
|
|
configure_logging(settings.log_level)
|
|
|
|
app = FastAPI(
|
|
title="GeoIntel Kempen",
|
|
version=settings.app_version,
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origins,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
allow_credentials=True,
|
|
)
|
|
|
|
app.include_router(health.router)
|
|
app.include_router(analysis.router, prefix=settings.api_prefix)
|
|
app.include_router(projects.router, prefix=settings.api_prefix)
|
|
app.include_router(areas.router, prefix=settings.api_prefix)
|
|
app.include_router(datasets.router, prefix=settings.api_prefix)
|
|
app.include_router(jobs.router, prefix=settings.api_prefix)
|
|
app.include_router(quality_checks.router, prefix=settings.api_prefix)
|
|
app.include_router(exports.router, prefix=settings.api_prefix)
|
|
app.include_router(external.router, prefix=settings.api_prefix)
|
|
app.include_router(demo.router, prefix=settings.api_prefix)
|
|
app.include_router(qa.router, prefix=settings.api_prefix)
|
|
app.include_router(detection.router, prefix=settings.api_prefix)
|
|
app.include_router(segmentation.router, prefix=settings.api_prefix)
|
|
|
|
@app.exception_handler(AppError)
|
|
async def app_error(request: Request, exc: AppError): # noqa: ARG001
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=_to_error_payload(exc.code, exc.message, exc.details),
|
|
)
|
|
|
|
@app.exception_handler(HTTPException)
|
|
async def http_error(request: Request, exc: HTTPException): # noqa: ARG001
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=_to_error_payload("HTTP_ERROR", str(exc.detail), {}),
|
|
)
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def validation_error(request: Request, exc: RequestValidationError): # noqa: ARG001
|
|
return JSONResponse(
|
|
status_code=422,
|
|
content=_to_error_payload("VALIDATION_ERROR", "Validation failed", exc.errors()),
|
|
)
|
|
|
|
@app.exception_handler(Exception)
|
|
async def unexpected_error(request: Request, exc: Exception): # noqa: ARG001
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content=_to_error_payload("INTERNAL_ERROR", "Unexpected server error", {"type": exc.__class__.__name__}),
|
|
)
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|
|
|
|
|
|
def main() -> None:
|
|
import uvicorn
|
|
|
|
settings = get_settings()
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host="0.0.0.0",
|
|
port=8000,
|
|
reload=settings.app_env == "development",
|
|
)
|