This repository has been archived on 2021-08-10. You can view files and clone it, but cannot push or open issues or pull requests.
gtools/router/errors.go

103 lines
2.5 KiB
Go

package router
import (
"fmt"
"net/http"
)
// ErrorResponder responds with error
type ErrorResponder interface {
RespondError(w http.ResponseWriter, r *http.Request, re *Router) bool
}
// HTTPStatusError http statuscode errors
type HTTPStatusError struct {
statuscode int
err error
body interface{}
output bool
}
// HTTPError handle HTTP error
func HTTPError(statuscode int, err error) *HTTPStatusError {
return &HTTPStatusError{statuscode: statuscode, err: err}
}
// HTTPErrorWithBody handle HTTP error with body
func HTTPErrorWithBody(body interface{}, statuscode int, err error) *HTTPStatusError {
return &HTTPStatusError{body: body, statuscode: statuscode, err: err}
}
// HTTPErrorWithReport handle HTTP error returning status report
func HTTPErrorWithReport(statuscode int, err error) *HTTPStatusError {
return &HTTPStatusError{statuscode: statuscode, err: err, output: true}
}
// RespondError HTTP error response
func (e *HTTPStatusError) RespondError(w http.ResponseWriter, r *http.Request, re *Router) bool {
if e.err != nil {
if e.statuscode >= 200 && e.statuscode <= 499 {
re.logger.Error.Warn(e.err)
} else {
re.logger.Error.Error(e.err)
}
}
if e.output {
re.Respond(struct {
Status string
Error string
}{
Status: fmt.Sprintf("%d %s", e.statuscode, http.StatusText(e.statuscode)),
Error: e.err.Error(),
}, e.statuscode).ServeHTTP(w, r)
} else if e.body == nil {
re.handleError(e.statuscode).ServeHTTP(w, r)
} else {
re.Respond(e.body, e.statuscode).ServeHTTP(w, r)
}
return true
}
// Error returns HTTP error
func (e *HTTPStatusError) Error() string {
return e.err.Error()
}
// WithError error handler
func (re *Router) WithError(h HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := h(w, r); err != nil {
if er, ok := err.(ErrorResponder); ok {
if er.RespondError(w, r, re) {
return
}
}
re.logger.Error.Error(err)
re.handleError(http.StatusInternalServerError).ServeHTTP(w, r)
}
}
}
func (re *Router) handleError(statuscode int) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
re.logger.AccessMessage(r, statuscode)
w.WriteHeader(statuscode)
re.RenderTemplate(struct {
Title string
Status struct {
Status string
StatusCode int
}
}{
Title: http.StatusText(statuscode),
Status: struct {
Status string
StatusCode int
}{
Status: http.StatusText(statuscode),
StatusCode: statuscode,
},
}).ServeHTTP(w, r)
}
}