package main import ( "bytes" "encoding/json" "encoding/xml" "html/template" "log" "net/http" ) func renderTemplate[T any](w http.ResponseWriter, r *http.Request, status int, templates *template.Template, template string, response T) error { buffer := bytes.Buffer{} if err := templates.Lookup(template).Execute(&buffer, response); err == nil { w.Header().Add("content-type", "text/html; charset=utf-8") w.WriteHeader(status) _, err = w.Write(buffer.Bytes()) return err } else { return onError(w, err) } } func onError(w http.ResponseWriter, err error) error { w.WriteHeader(http.StatusInternalServerError) log.Printf("failed writing response: %v", err) _, _ = w.Write([]byte{}) return err } func render[T any](w http.ResponseWriter, r *http.Request, status int, response T) error { switch r.Header.Get("accept") { case "application/xml": fallthrough case "text/xml": if body, err := xml.MarshalIndent(response, "", " "); err == nil { // we return the same type as requested w.Header().Add("content-type", r.Header.Get("accept")+"; charset=utf-8") w.WriteHeader(status) _, err = w.Write([]byte(xml.Header)) _, err = w.Write(body) return err } else { return onError(w, err) } case "application/json": fallthrough default: if body, err := json.MarshalIndent(response, "", " "); err == nil { w.Header().Add("content-type", "application/json; charset=utf-8") w.WriteHeader(status) _, err = w.Write(body) return err } else { return onError(w, err) } } }