GZip, Cache-Dauer fuer statische Dateien, Sicherungsskript

GZip: Die Startseite ging unkomprimiert raus - 9725 Byte, jetzt 1900.
Zuletzt angemeldet heisst zuerst ausgefuehrt, die Komprimierung liegt damit
aussen.

Statische Dateien: StaticFiles kennt keine Cache-Dauer, per Unterklasse
nachgeruestet. Bewusst nur eine Stunde - die Dateien tragen keinen
Versionsanhaenger, eine lange Dauer wuerde nach einem Update die alte
Fassung festhalten. (Die hochgeladenen Bilder hatten ihre Header laengst;
der Plan behauptete faelschlich das Gegenteil, korrigiert.)

Sicherung: sicherung.sh sichert Datenbank UND Bilder - eine Datenbank ohne
die Fotos ist wertlos. Pfade werden aus der Anwendung gelesen statt geraten.
Die Pruefung oeffnet die Kopie, nicht das Original. Erprobt: 4 Eintraege,
4 Bilder, vollstaendig; ein entferntes Bild wird erkannt.

81 Tests weiterhin gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
This commit is contained in:
2026-09-13 21:08:44 +02:00
co-authored by Claude Opus 5
parent c748013e4a
commit c9861613cc
3 changed files with 136 additions and 6 deletions
+26 -1
View File
@@ -12,6 +12,7 @@ from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
from fastapi.staticfiles import StaticFiles
from slowapi.errors import RateLimitExceeded
@@ -75,6 +76,11 @@ app.add_middleware(
max_age=_cfg.sitzung_max_ruhe_sekunden,
)
# Zuletzt angemeldet heisst zuerst ausgefuehrt: die Komprimierung liegt damit
# aussen und erfasst auch die Antworten der uebrigen Middleware. Unter 1000
# Byte lohnt sie nicht - der Kopf der gzip-Huelle frisst den Gewinn auf.
app.add_middleware(GZipMiddleware, minimum_size=1000)
app.state.limiter = limiter
@@ -123,7 +129,26 @@ app.include_router(images.router)
app.include_router(pages.router)
app.mount("/static", StaticFiles(directory=Path(__file__).parent / "static"), name="static")
class StatischMitCache(StaticFiles):
"""StaticFiles kennt keine Cache-Dauer - hier nachgeruestet.
Ohne das verhandelt der Browser htmx.min.js, theme.js und die beiden
Swagger-Dateien bei jedem Seitenaufruf neu. Eine Stunde, nicht ein Jahr:
die Dateien tragen keinen Versionsanhaenger im Namen, eine lange Dauer
wuerde nach einem Update die alte Fassung festhalten.
"""
def file_response(self, *args, **kwargs):
antwort = super().file_response(*args, **kwargs)
antwort.headers.setdefault("Cache-Control", "public, max-age=3600")
return antwort
app.mount(
"/static",
StatischMitCache(directory=Path(__file__).parent / "static"),
name="static",
)
@app.get("/docs", include_in_schema=False)