// Package api provides small HTTP helpers shared by the HTTP handlers. package api import ( "encoding/json" "net/http" ) // Error is an error that serializes to the shape {"error": message}. type Error struct { Err string `json:"error"` } // Error returns the error message. func (e Error) Error() string { return e.Err } // NewError returns an Error with the given message. func NewError(msg string) error { return Error{Err: msg} } // WriteJSON writes a JSON response. A nil payload writes only the status code. func WriteJSON(w http.ResponseWriter, status int, payload any) { if payload == nil { w.WriteHeader(status) return } data, err := json.Marshal(payload) if err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) _, _ = w.Write([]byte(`{"error":"Failed to encode JSON response"}`)) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) _, _ = w.Write(data) } // WriteError writes an error response with the given status code. func WriteError(w http.ResponseWriter, status int, msg string) { WriteJSON(w, status, Error{Err: msg}) } // DecodeJSON decodes a JSON request body into a new value of type T. func DecodeJSON[T any](r *http.Request) (*T, error) { defer r.Body.Close() decoder := json.NewDecoder(r.Body) var data *T if err := decoder.Decode(&data); err != nil { return nil, NewError("Failed to deserialize request") } return data, nil }