import sqlite3 from contextlib import asynccontextmanager from pathlib import Path from urllib.parse import urlsplit from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from database import initialize from routes import dashboard, income, export from api.routes import router as api_router @asynccontextmanager async def lifespan(app): initialize() yield app = FastAPI(title='Finance Dashboard', lifespan=lifespan) app.mount('/static', StaticFiles(directory=Path(__file__).parent / 'static'), name='static') app.include_router(dashboard.router) app.include_router(income.router) app.include_router(export.router) app.include_router(api_router) @app.middleware('http') async def protect_forms(request: Request, call_next): if request.method == 'POST' and not request.url.path.startswith('/api/v1/'): origin = request.headers.get('origin') if request.headers.get('sec-fetch-site') == 'cross-site' or (origin and urlsplit(origin).netloc != request.headers.get('host')): return HTMLResponse('Fremder Formularursprung ist nicht erlaubt.', status_code=403) return await call_next(request) @app.exception_handler(sqlite3.OperationalError) async def database_error(request, error): return HTMLResponse('

Datenbank vorübergehend nicht verfügbar

Bitte in einigen Sekunden erneut versuchen.

Zum Dashboard', status_code=503, headers={'Retry-After': '5'}) @app.get('/health') def health(): return {'status': 'ok'}