// Package httputil contains thin JSON-response and error-routing helpers. package httputil import ( "encoding/json" "log/slog" "net/http" "go.bigb.es/auxilia/scribe" "sourcecraft.dev/bigbes/huntsman/internal/pkg/apierror" ) // JSON writes a JSON response with the given status code. func JSON(w http.ResponseWriter, status int, data any) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) if data != nil { _ = json.NewEncoder(w).Encode(data) } } // OK is the common 200 path. func OK(w http.ResponseWriter, data any) { JSON(w, http.StatusOK, data) } // Error converts err into a Problem response. Internal (5xx) errors are // logged with the original error message; client errors are not, since // they're not actionable for the operator. func Error(w http.ResponseWriter, r *http.Request, err error) { problem := apierror.FromError(err) if problem.Status >= 500 { //nolint:gosec // G706: slog handlers escape attribute values, so r.URL.Path cannot inject newlines into log output. slog.Error("internal error", "path", r.URL.Path, scribe.Err(err)) } problem.Write(w) }