diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-20 07:18:42 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-20 07:18:42 +0300 |
| commit | 925ef996f2661f5e5cf57a1cd5a842303578330c (patch) | |
| tree | 6d4810e4393f33ede7d23c63c60a20c1f52a1b16 /player-server/internal/api/handlers.go | |
| parent | f45737298d9536819c094ab90917db362b28332a (diff) | |
Buffer JSON before writing response in writeJSON (y9)
Previously writeJSON wrote the status header before encoding, so an
encode failure produced a misleading 200 (or other caller status) with
a truncated body. Marshal into a bytes.Buffer first; on error emit 500
with a JSON error envelope instead.
Diffstat (limited to 'player-server/internal/api/handlers.go')
| -rw-r--r-- | player-server/internal/api/handlers.go | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/player-server/internal/api/handlers.go b/player-server/internal/api/handlers.go index f04ec19..8635c92 100644 --- a/player-server/internal/api/handlers.go +++ b/player-server/internal/api/handlers.go @@ -1,6 +1,7 @@ package api import ( + "bytes" "encoding/json" "errors" "fmt" @@ -26,12 +27,26 @@ func fileETag(size int64, modTime time.Time) string { // Helpers // ------------------------------------------------------------------ +// writeJSON serialises data to JSON and writes it to w with the given status. +// +// Marshalling happens into an in-memory buffer BEFORE any status or body is +// written to the response. This avoids the previous footgun where the headers +// (and a 200/whatever status) were committed first and then encoding failed +// halfway through, producing a response with a misleading success status and a +// truncated/invalid body. If encoding fails we instead emit a 500 with a small +// JSON error payload so callers always see a consistent error shape. func writeJSON(w http.ResponseWriter, status int, data interface{}) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(status) - if err := json.NewEncoder(w).Encode(data); err != nil { + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(data); err != nil { slog.Error("encode json", "err", err) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(`{"error":"internal encoding error"}`)) + return } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + _, _ = w.Write(buf.Bytes()) } func writeError(w http.ResponseWriter, status int, message string) { |
