SSR-Renderer entfernt, Fokus auf SPA + JSON-API

Die Kernlogik bleibt von der Schnittstelle getrennt; der letzte SSR-Stand
liegt im Tag ssr-archiv. Die Moderationsseite bleibt, liefert Fehler aber
als JSON.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
irrlicht
2026-09-26 21:28:34 +02:00
co-authored by Claude Opus 5.5
parent eccddcebe6
commit c6ab082f8c
26 changed files with 50 additions and 2603 deletions
+1 -26
View File
@@ -103,9 +103,6 @@ func routes() http.Handler {
// zusätzlich, aber das Limit kappt automatisiertes Durchprobieren früh.
r.Group(func(r chi.Router) {
r.Use(httprate.LimitByIP(20, time.Minute))
// handleLogin bedient JSON- und Formular-Clients (siehe wantsJSON) und
// schreibt HTML-Antworten selbst -- api() greift nur noch für den
// JSON-Zweig.
r.Post("/auth/login", api(handleLogin))
r.Post("/auth/newuser", api(handleNewUser))
})
@@ -113,19 +110,6 @@ func routes() http.Handler {
// Navigationen mit -- als GET könnte eine fremde Seite Nutzer per Link
// ausloggen (CSRF). POST ist durch Lax + checkOrigin gedeckt.
r.Post("/auth/logout", handleLogout)
// Serverseitig gerenderte Auth-Seiten (noscript-Weg). Kein Rate-Limit: das
// bloße Anzeigen der Formulare ist kein Brute-Force-Vektor, die POSTs oben
// sind gedrosselt.
r.Get("/auth/login", page(showLogin))
r.Get("/auth/register", page(showRegister))
// Serverseitig gerenderte Feeds. Eigene Pfade, solange "/" und "/u/{name}"
// noch die JS-Varianten ausliefern -- so bleibt die Seite während des
// Umbaus durchgehend benutzbar. Sobald das Frontend auf gerendertem Markup
// aufsetzt, übernehmen diese Handler die ursprünglichen Pfade.
r.With(trackImpression).Get("/feed", page(showFeed))
r.With(trackImpression).Get("/u/{username}/beitraege", page(showUserFeed))
r.With(trackImpression).Get("/beitrag/{pid}", page(showThread))
r.Get("/auth/sessioninfo", api(handleSessionInfo))
r.Get("/auth/headerbar", handleHeaderbar)
r.Get("/stats", handleStats)
@@ -135,7 +119,7 @@ func routes() http.Handler {
// weil TOR-Zugriffe die Go-App direkt erreichen und NICHT über Caddy laufen --
// ein rein proxy-seitiger Schutz hätte diese Lücke offen gelassen. Caddy
// erzwingt zusätzlich TLS für den Clearnet-Weg.
r.With(modBasicAuth).Get("/moderation", page(handleModeration))
r.With(modBasicAuth).Get("/moderation", api(handleModeration))
// HTML-Seiten: mit Impression-Tracking (anonymisiert, siehe stats.go). Nur
// echte Seitenaufrufe, nicht API/Assets.
@@ -150,9 +134,6 @@ func routes() http.Handler {
// Melden: öffentlich (jeder darf melden, Moderationshilfe), aber pro IP
// gedrosselt, damit der auth-lose Endpunkt nicht zum Spam-Kanal wird.
r.With(httprate.LimitByIP(10, time.Minute)).Post("/entry/{pid}/report", api(handleReport))
// Bestätigungsseite nach einer Meldung ohne JavaScript. Reines Anzeigen,
// deshalb ohne Rate-Limit -- gemeldet wird im POST darüber.
r.Get("/entry/{pid}/gemeldet", page(showReported))
// --- User (öffentlich) ---
r.With(trackImpression).Get("/u/{username}", serveUserPage)
@@ -166,12 +147,6 @@ func routes() http.Handler {
r.Post("/entry/{pid}/vote", api(handleVote))
r.Post("/entry/{pid}/bump", api(handleBump))
r.Post("/entry/{pid}/edit", api(handleEditEntry))
// Bearbeitungsformular (noscript-Weg). In der requireAuth-Gruppe, weil
// nur der Autor den bisherigen Text zu sehen bekommen soll.
r.Get("/beitrag/{pid}/bearbeiten", page(showEditEntry))
// Löschbestätigung: das eigentliche Löschen bleibt ein POST, damit ein
// gefolgter Link (Linkvorschau, Crawler) nichts vernichtet.
r.Get("/beitrag/{pid}/loeschen", page(showDeleteEntry))
r.Post("/entry/{pid}/delete", api(handleDeleteEntry))
r.Get("/user/info", api(handleUserInfo))
r.Post("/user/rename", api(handleUserRename))