Files
playwish/server/app/main.py
T
99admandClaude Opus 5.5 3610de7bae Audiofy – Musikwünsche für Partys
Server (Website, Admin-Bereich, Player-API) und Player (raspotify +
Controller) mit Install-Skripten für Debian-Systeme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:16:39 +01:00

51 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Audiofy-Web – FastAPI-Anwendung.
Start (Server): uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 1 --no-access-log
Caddy terminiert HTTPS und leitet an 127.0.0.1:8000 weiter.
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from . import admin, db, gaeste, player_api
from .config import konfig
# Streng: nur eigene Skripte/Styles, Cover-Bilder vom Spotify-CDN, Turnstile von Cloudflare
CSP = ("default-src 'self'; script-src 'self' https://challenges.cloudflare.com; style-src 'self'; "
"img-src 'self' https://i.scdn.co data:; frame-src https://challenges.cloudflare.com; "
"connect-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'")
@asynccontextmanager
async def lifespan(app: FastAPI):
k = konfig()
db.initialisieren(k.db_pfad, k.playlist_id)
yield
# Keine automatische API-Doku öffentlich ausliefern
app = FastAPI(title="Audiofy – Musikwünsche", lifespan=lifespan, docs_url=None, redoc_url=None, openapi_url=None)
@app.middleware("http")
async def sicherheits_header(request: Request, call_next):
antwort = await call_next(request)
antwort.headers.setdefault("Content-Security-Policy", CSP)
if request.url.path.startswith("/api/"):
antwort.headers.setdefault("Cache-Control", "no-store")
return antwort
app.include_router(player_api.router, prefix="/api/player")
app.include_router(player_api.router, prefix="/api/pi", include_in_schema=False) # alter Pfad, für ältere Player
app.include_router(gaeste.router)
app.include_router(admin.router)
app.mount("/static", StaticFiles(directory=gaeste.STATIC), name="static")
@app.get("/healthz")
def healthz() -> dict:
return {"ok": True}