SSR: Repost ohne JS, return_to in Formularen, Werbebanner entfernt

Letzter vollständiger SSR-Stand vor dem Rückbau auf reine SPA.

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:23:09 +02:00
co-authored by Claude Opus 5.5
parent c66df283d1
commit eccddcebe6
9 changed files with 194 additions and 45 deletions
+21 -5
View File
@@ -496,11 +496,20 @@ func handleBump(w http.ResponseWriter, r *http.Request) error {
if remaining < 0 {
remaining = 0
}
// Bewusst kein Taxonomie-Fehler: die Antwort trägt Nutzdaten
// (retry_after, bump_count), die das Frontend zum Sperren des Buttons
// braucht -- ein reiner Fehlerkörper kann die nicht transportieren.
// Der Cooldown ist auch kein Fehlerfall, sondern ein regulärer
// Ausgang des Bumpens.
// Ohne JavaScript: der Cooldown ist eine eigene Fehlerseite mit der
// Restzeit -- ein stiller Rücksprung wäre von "hat geklappt" nicht zu
// unterscheiden.
if !wantsJSON(r) {
hours := (remaining + 3599) / 3600
if hours < 1 {
hours = 1
}
return RateLimited("entry.bump_cooldown", fmt.Sprintf(
"Dieser Beitrag wurde erst kürzlich repostet. Nächster Repost in etwa %d Stunde(n).", hours))
}
// JSON-Zweig: bewusst kein Taxonomie-Fehler -- die Antwort trägt
// Nutzdaten (retry_after, bump_count), die das Frontend zum Sperren des
// Buttons braucht, und der Cooldown ist ein regulärer Ausgang.
w.Header().Set("Retry-After", strconv.FormatInt(remaining, 10))
writeJSON(w, http.StatusTooManyRequests, map[string]any{
"error": apiErrorBody{
@@ -512,6 +521,13 @@ func handleBump(w http.ResponseWriter, r *http.Request) error {
})
return nil
}
// Ohne JavaScript zurück an den Beitrag, auf dem repostet wurde -- der
// Anker in return_to hält die Position.
if !wantsJSON(r) {
redirectBack(w, r, threadAnchor(pid))
return nil
}
writeJSON(w, http.StatusOK, map[string]any{
"pid": pid,
"bump_count": bumpCount,