Files
Aether/backend/pkg/middleware/logger.go
T
marcandClaude Opus 5 2cc02941b9 fix(files): beschaedigte Downloads werden gemeldet und abgebrochen
Die Pruefsumme wurde beim Ausliefern mitgerechnet und das Ergebnis
weggeworfen -- ein gekipptes Bit wurde erkannt und verschwiegen.

Jetzt: Logeintrag mit Datei-ID, Speicherschluessel, erwarteter und
gelesener Summe, dazu panic(http.ErrAbortHandler), den chis Recoverer
ausdruecklich durchreicht.

Damit das wirkt, werden die letzten 32 KiB zurueckgehalten. Sonst waere die
Datei beim Erkennen laengst vollstaendig beim Empfaenger und der Abbruch
kaeme zu spaet. Erst wenn die Summe stimmt, darf der Schluss hinterher;
sonst bekommt die Gegenstelle weniger Bytes als angekuendigt und wertet das
als Fehler statt als Datei.

scripts/pruefsumme-selbsttest.py, 14 Pruefungen: kippt ein Bit auf der
Platte (nicht im Programm), in der Mitte der Datei, damit es nicht schon an
der Laenge auffaellt; zwei Groessen ueber und unter den 32 KiB; und zuerst
die Gegenprobe, dass eine heile Datei durchkommt.

**Dabei gefunden:** Der neue Logeintrag blieb aus, obwohl der Abbruch
funktionierte. zerolog.Ctx liefert einen *abgeschalteten* Logger, wenn im
Kontext keiner steckt -- und Aether legte nie einen hinein. Alle 34
log.Ctx-Aufrufe im Baum schrieben ins Nichts, darunter die Warnung ueber
verwaiste Blobs beim Zurueckrollen einer Fassung.

Behoben zweifach: zerolog.DefaultContextLogger beim Start (deckt auch
Hintergrundarbeit ab) und ein Logger mit request_id im Anfragekontext. Zwei
Tests halten es fest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 22:15:22 +02:00

57 lines
1.4 KiB
Go
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.
package middleware
import (
"net/http"
"time"
chimiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func Logger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := &responseWriter{ResponseWriter: w, status: http.StatusOK}
// Den Logger in den Kontext hängen, damit log.Ctx(r.Context()) in den
// Handlern etwas findet – und damit jede Zeile aus einer Anfrage die
// Kennung dieser Anfrage trägt. Ohne das schreibt log.Ctx gar nicht
// (zerolog gibt dann einen abgeschalteten Logger zurück), und mit
// einem globalen Standard allein ließe sich nicht mehr zuordnen,
// welche Meldung zu welchem Aufruf gehört.
l := log.Logger.With().
Str("request_id", chimiddleware.GetReqID(r.Context())).
Logger()
r = r.WithContext(l.WithContext(r.Context()))
next.ServeHTTP(ww, r)
level := zerolog.InfoLevel
if ww.status >= 500 {
level = zerolog.ErrorLevel
} else if ww.status >= 400 {
level = zerolog.WarnLevel
}
log.WithLevel(level).
Str("method", r.Method).
Str("path", r.URL.Path).
Int("status", ww.status).
Dur("duration", time.Since(start)).
Str("ip", r.RemoteAddr).
Msg("")
})
}
type responseWriter struct {
http.ResponseWriter
status int
}
func (rw *responseWriter) WriteHeader(status int) {
rw.status = status
rw.ResponseWriter.WriteHeader(status)
}