2021-03-09 01:32:31 +00:00
|
|
|
package router
|
|
|
|
|
|
|
|
import (
|
2021-03-21 19:58:20 +00:00
|
|
|
"fmt"
|
2021-03-09 01:32:31 +00:00
|
|
|
"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{}
|
2021-03-21 19:58:20 +00:00
|
|
|
output bool
|
2021-03-09 01:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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}
|
|
|
|
}
|
|
|
|
|
2021-03-21 19:58:20 +00:00
|
|
|
// HTTPErrorWithReport handle HTTP error returning status report
|
|
|
|
func HTTPErrorWithReport(statuscode int, err error) *HTTPStatusError {
|
|
|
|
return &HTTPStatusError{statuscode: statuscode, err: err, output: true}
|
|
|
|
}
|
|
|
|
|
2021-03-09 01:32:31 +00:00
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
}
|
2021-03-21 19:58:20 +00:00
|
|
|
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 {
|
2021-03-09 01:32:31 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|