feat(smalltrip,problems): use Problem interface on handlers
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user