gocommon/middleware/recovery.go

55 lines
1.7 KiB
Go
Raw Normal View History

package middleware
import (
"fmt"
"net/http"
"git.dev.m-and-m.ovh/mderasse/gocommon/commonctx"
)
type recoveryFuncSignature func(w http.ResponseWriter, r *http.Request)
type recoveryMiddleware struct {
handler http.Handler
respFunc recoveryFuncSignature
}
func (rm *recoveryMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
// log the error
log := commonctx.GetLogger(r.Context())
if log == nil {
fmt.Print("Impossible to log the panic as the logger is not part of the context\n")
} else {
// Probably have to catch a stacktrace + Info about the error
log.Error("A Panic happened and has been caught")
}
// execute the recovery function
rm.respFunc(w, r)
}
}()
rm.handler.ServeHTTP(w, r)
}
// NewRecoveryMiddleware will declare a new middleware on the provided handler. It will recover any panic and log it.
// By default, the middleware will return a default error object in json with a 500 Http code. That can be overide by providing a recoveryFunc.
func NewRecoveryMiddleware(h http.Handler, recoveryFunc recoveryFuncSignature) *recoveryMiddleware {
recovery := &recoveryMiddleware{
handler: h,
respFunc: recoveryFunc,
}
if recovery.respFunc == nil {
recovery.respFunc = func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(
fmt.Sprintf("{\"code\":%d,\"message\":\"An error happened during the execution of your request.\"}", http.StatusInternalServerError),
))
}
}
return recovery
}