feat(smalltrip,problems): use Problem interface on handlers

This commit is contained in:
Guz
2025-07-29 19:18:28 -03:00
parent 22f2ea5fa8
commit ed8f1e9601

View File

@@ -8,91 +8,90 @@ import (
"strings" "strings"
) )
func ProblemHandler(p any) http.Handler { type Handler func(p Problem) http.Handler
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := r.Header.Get("Accept") func HandlerAll(p Problem) http.Handler {
if strings.Contains(h, "application/xml") || strings.Contains(h, ProblemMediaTypeXML) { h := HandlerContentType(map[string]Handler{
ProblemHandlerXML(p).ServeHTTP(w, r) "application/xml": HandlerXML,
return ProblemMediaTypeXML: HandlerXML,
} "application/json": HandlerJSON,
ProblemHandlerJSON(p).ServeHTTP(w, r) ProblemMediaTypeJSON: HandlerJSON,
}) }, HandlerJSON)
return h(p)
} }
func ProblemHandlerXML(p any) http.Handler { func HandlerContentType(handlers map[string]Handler, fallback ...Handler) Handler {
return func(p Problem) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for t, h := range handlers {
if strings.Contains(r.Header.Get("Accept"), t) {
h(p).ServeHTTP(w, r)
return
}
}
if len(fallback) > 0 {
fallback[0](p).ServeHTTP(w, r)
}
})
}
}
func HandlerXML(p Problem) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// w.Header().Set("Content-Type", ProblemMediaTypeXML) w.Header().Set("Content-Type", ProblemMediaTypeXML)
w.Header().Set("Content-Type", "application/xml")
b, err := xml.Marshal(p) b, err := xml.Marshal(p)
if err != nil { if err != nil {
ProblemHandlerJSON(p).ServeHTTP(w, r) HandlerJSON(p).ServeHTTP(w, r)
return return
} }
w.WriteHeader(GetStatus(p)) w.WriteHeader(p.Status())
_, err = w.Write(b) _, err = w.Write(b)
if err != nil { if err != nil {
ProblemHandlerJSON(p).ServeHTTP(w, r) HandlerJSON(p).ServeHTTP(w, r)
} }
}) })
} }
func ProblemHandlerJSON(p any) http.Handler { func HandlerJSON(p Problem) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", ProblemMediaTypeJSON) w.Header().Set("Content-Type", ProblemMediaTypeJSON)
b, err := json.Marshal(p) b, err := json.Marshal(p)
if err != nil { if err != nil {
ProblemHandlerText(p).ServeHTTP(w, r) HandlerText(p).ServeHTTP(w, r)
return return
} }
w.WriteHeader(GetStatus(p)) w.WriteHeader(p.Status())
_, err = w.Write(b) _, err = w.Write(b)
if err != nil { if err != nil {
ProblemHandlerText(p).ServeHTTP(w, r) HandlerText(p).ServeHTTP(w, r)
} }
}) })
} }
func ProblemHandlerText(p any) http.Handler { func HandlerText(p Problem) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain") w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(GetStatus(p)) w.WriteHeader(p.Status())
var s string s := fmt.Sprintf(
if p, ok := p.(Problem); ok { "Type: %s\n"+
s = fmt.Sprintf( "Status: %3d\n"+
"Type: %s\n"+ "Title: %s\n"+
"Status: %3d\n"+ "Detail: %s\n"+
"Title: %s\n"+ "Instance: %s\n\n"+
"Detail: %s\n"+ p.Type(),
"Instance: %s\n\n"+ p.Status(),
p.Type, p.Title(),
p.Status, p.Detail(),
p.Title, p.Instance(),
p.Detail, )
p.Instance,
)
}
if p, ok := p.(*Problem); ok {
s = fmt.Sprintf(
"Type: %s\n"+
"Status: %3d\n"+
"Title: %s\n"+
"Detail: %s\n"+
"Instance: %s\n\n"+
p.Type,
p.Status,
p.Title,
p.Detail,
p.Instance,
)
}
_, err := w.Write(fmt.Appendf([]byte{}, "%s%+v\n\n%#v", s, p, p)) _, err := w.Write(fmt.Appendf([]byte{}, "%s%+v\n\n%#v", s, p, p))
if err != nil { if err != nil {
@@ -112,13 +111,6 @@ func ProblemHandlerText(p any) http.Handler {
}) })
} }
func GetStatus(p any) int {
if p, ok := p.(interface{ StatusCode() int }); ok {
return p.StatusCode()
}
return http.StatusInternalServerError
}
const ( const (
ProblemMediaTypeJSON = "application/problem+json" ProblemMediaTypeJSON = "application/problem+json"
ProblemMediaTypeXML = "application/problem+xml" ProblemMediaTypeXML = "application/problem+xml"