fix(10.1): WR-04 judge action fill values by their JSON encoding

isJSONScalar now encodes each value and keeps it only when the encoding
is a string, number, boolean or null, so a named scalar whose MarshalJSON
writes an array or object, NaN and the infinities are dropped. writeJSON
encodes into a buffer before the status line, so an encode failure is a
logged 500 with the generic envelope instead of a 200 with a truncated
body.
This commit is contained in:
Jakub Zych
2026-09-29 09:56:44 +02:00
parent 7333f450ad
commit 0bdb6ebcac
5 changed files with 98 additions and 22 deletions

View File

@@ -1,7 +1,9 @@
package cabana
import (
"bytes"
"encoding/json"
"log/slog"
"net/http"
"strings"
"time"
@@ -187,8 +189,20 @@ func WriteErrorDetails(w http.ResponseWriter, status int, code, message string,
})
}
// writeJSON encodes body before the status line goes out, so a value that
// cannot be encoded (NaN, an infinity, a failing MarshalJSON) is a logged 500
// with the generic body instead of a 200 with a truncated one.
func writeJSON(w http.ResponseWriter, status int, body any) {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(body); err != nil {
slog.Error("cabana: response could not be encoded", "status", status, "error", err)
buf.Reset()
_ = json.NewEncoder(&buf).Encode(map[string]any{
"error": map[string]any{"code": "error", "message": msgServerError, "details": map[string]any{}},
})
status = http.StatusInternalServerError
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(body)
_, _ = w.Write(buf.Bytes())
}