Moderation entfernt, JSON-API unter /api
- Moderationsseite und Melde-Funktion (report) komplett ausgebaut; folgt als eigenständiges Projekt - alle API-Endpunkte unter /api, dort ausschließlich JSON: auch 404, 405, Rate-Limit (429) und Panics (500) - Fehler nur über HTTP-Status; stille DB-Fehler in stats, logout und Vote-Zählern liefern jetzt 500 statt Nullen - /auth/headerbar entfernt (Frontend nutzt /api/user/info) - Frontend auf /api und statusbasierte Auswertung umgestellt - notes/api.md neu als Referenz der aktuellen API Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2714fdb1a5
commit
030a5bd943
@@ -10,23 +10,22 @@ import (
|
||||
// Fehler-Aufrufstelle verklebt waren -- wie schwer der Fehler ist (Kind),
|
||||
// was genau passiert ist (Code) und was der Nutzer lesen soll (Msg).
|
||||
//
|
||||
// Der Sinn der Trennung: derselbe Fehler muss künftig von zwei Adaptern
|
||||
// unterschiedlich dargestellt werden. Der HTML-Pfad braucht Msg und Field, um
|
||||
// ein Formular mit Fehlermarkierung neu zu rendern; ein API-Client braucht
|
||||
// Code, um ohne Parsen deutscher Strings reagieren zu können.
|
||||
// Der Sinn der Trennung: das Frontend zeigt Msg an und markiert Field, ein
|
||||
// Client braucht Code, um ohne Parsen deutscher Strings reagieren zu können,
|
||||
// und der HTTP-Status ergibt sich allein aus Kind.
|
||||
|
||||
type Kind uint8
|
||||
|
||||
const (
|
||||
KindInternal Kind = iota // Bug oder Infrastruktur -- Ursache nie nach außen
|
||||
KindInvalid // Eingabe passt nicht
|
||||
KindUnauth // nicht angemeldet
|
||||
KindForbidden // angemeldet, aber nicht erlaubt
|
||||
KindNotFound // Objekt existiert nicht (oder soll nicht sichtbar sein)
|
||||
KindConflict // Name vergeben, Doppel-Post
|
||||
KindTooLarge // Upload über dem Limit
|
||||
KindRateLimited // zu viele Anfragen
|
||||
KindUnavailable // Feature nicht konfiguriert
|
||||
KindInternal Kind = iota // Bug oder Infrastruktur -- Ursache nie nach außen
|
||||
KindInvalid // Eingabe passt nicht
|
||||
KindUnauth // nicht angemeldet
|
||||
KindForbidden // angemeldet, aber nicht erlaubt
|
||||
KindNotFound // Objekt existiert nicht (oder soll nicht sichtbar sein)
|
||||
KindConflict // Name vergeben, Doppel-Post
|
||||
KindTooLarge // Upload über dem Limit
|
||||
KindRateLimited // zu viele Anfragen
|
||||
KindMethodNotAllowed // Route existiert, aber nicht mit dieser Methode
|
||||
)
|
||||
|
||||
// Error ist der Fehlertyp, den die Service-Schicht nach oben gibt. Kind ist
|
||||
@@ -56,7 +55,9 @@ func NotFound(code, msg string) *Error { return &Error{Kind: KindNotFound, Co
|
||||
func Conflict(code, msg string) *Error { return &Error{Kind: KindConflict, Code: code, Msg: msg} }
|
||||
func TooLarge(code, msg string) *Error { return &Error{Kind: KindTooLarge, Code: code, Msg: msg} }
|
||||
func RateLimited(code, msg string) *Error { return &Error{Kind: KindRateLimited, Code: code, Msg: msg} }
|
||||
func Unavailable(code, msg string) *Error { return &Error{Kind: KindUnavailable, Code: code, Msg: msg} }
|
||||
func MethodNotAllowed(code, msg string) *Error {
|
||||
return &Error{Kind: KindMethodNotAllowed, Code: code, Msg: msg}
|
||||
}
|
||||
|
||||
// Internal verschluckt die Ursache absichtlich: der Nutzer sieht nie einen
|
||||
// DB- oder Dateisystemfehler (der Interna und Pfade verraten würde), das Log
|
||||
@@ -102,9 +103,7 @@ func asError(err error) *Error {
|
||||
return Internal(err)
|
||||
}
|
||||
|
||||
// statusOf bildet Kind auf HTTP ab. Beide HTTP-Adapter (HTML und JSON) teilen
|
||||
// sich diese Zuordnung -- unterschiedliche Statuscodes für denselben Fehler
|
||||
// wären genau die Divergenz, die die Taxonomie verhindern soll.
|
||||
// statusOf bildet Kind auf HTTP ab -- die einzige Stelle, an der das passiert.
|
||||
func statusOf(k Kind) int {
|
||||
switch k {
|
||||
case KindInvalid:
|
||||
@@ -121,17 +120,15 @@ func statusOf(k Kind) int {
|
||||
return http.StatusRequestEntityTooLarge
|
||||
case KindRateLimited:
|
||||
return http.StatusTooManyRequests
|
||||
case KindUnavailable:
|
||||
return http.StatusServiceUnavailable
|
||||
case KindMethodNotAllowed:
|
||||
return http.StatusMethodNotAllowed
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
// logInternal protokolliert nur echte Serverfehler -- Validierungs- und
|
||||
// Rechtefehler sind normaler Betrieb und würden das Log zumüllen. Beide
|
||||
// Adapter rufen das auf, damit ein Fehler unabhängig vom Ausgabeformat
|
||||
// genau einmal im Log landet.
|
||||
// Rechtefehler sind normaler Betrieb und würden das Log zumüllen.
|
||||
func logInternal(e *Error) {
|
||||
if e.Kind != KindInternal {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user