Files

59 lines
1.4 KiB
Go
Raw Permalink Normal View History

// 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
}