121 lines
2.4 KiB
Go
121 lines
2.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"runtime/debug"
|
|
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
)
|
|
|
|
type recoverErr struct {
|
|
Error string `json:"error"`
|
|
Msg string `json:"msg"`
|
|
Code int `json:"code"`
|
|
}
|
|
|
|
func (e recoverErr) Json() string {
|
|
return fmt.Sprintf(`{"error":"%s","msg":"%s","code":%d}`, e.Msg, e.Error, e.Code)
|
|
}
|
|
|
|
// Close will panic anyway.
|
|
// Recoverer will catch the panic and return the error.
|
|
func Close(msg string, err any, status int) {
|
|
switch v := err.(type) {
|
|
case string:
|
|
panic(recoverErr{
|
|
Error: v,
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
case error:
|
|
panic(recoverErr{
|
|
Error: v.Error(),
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
default:
|
|
panic(recoverErr{
|
|
Error: fmt.Sprint(err),
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
}
|
|
}
|
|
|
|
// CloseIf will panic if hasErr is true.
|
|
// Recoverer will catch the panic and return the error.
|
|
func CloseIf(hasErr bool, msg string, err any, status int) {
|
|
if hasErr {
|
|
switch v := err.(type) {
|
|
case string:
|
|
panic(recoverErr{
|
|
Error: v,
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
case error:
|
|
panic(recoverErr{
|
|
Error: v.Error(),
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
default:
|
|
panic(recoverErr{
|
|
Error: fmt.Sprint(err),
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// CloseIfErr will panic if err is not nil.
|
|
// Recoverer will catch the panic and return the error.
|
|
func CloseIfErr(err error, msg string, status int) {
|
|
if err != nil {
|
|
panic(recoverErr{
|
|
Error: err.Error(),
|
|
Msg: msg,
|
|
Code: status,
|
|
})
|
|
}
|
|
}
|
|
|
|
// Recoverer edited from https://github.com/go-chi/chi/blob/master/middleware/recoverer.go
|
|
func Recoverer(next http.Handler) http.Handler {
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
defer func() {
|
|
if rvr := recover(); rvr != nil {
|
|
if rvr == http.ErrAbortHandler {
|
|
// we don't recover http.ErrAbortHandler so the response
|
|
// to the client is aborted, this should not be logged
|
|
panic(rvr)
|
|
}
|
|
|
|
if errs, ok := rvr.(recoverErr); ok {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(errs.Code)
|
|
Json(w, errs)
|
|
return
|
|
}
|
|
|
|
logEntry := middleware.GetLogEntry(r)
|
|
if logEntry != nil {
|
|
logEntry.Panic(rvr, debug.Stack())
|
|
} else {
|
|
middleware.PrintPrettyStack(rvr)
|
|
}
|
|
|
|
if r.Header.Get("Connection") != "Upgrade" {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
}
|
|
}()
|
|
|
|
next.ServeHTTP(w, r)
|
|
}
|
|
|
|
return http.HandlerFunc(fn)
|
|
}
|