github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gorilla/handlers/recovery.go (about) 1 package handlers 2 3 import ( 4 "github.com/hellobchain/newcryptosm/http" 5 "log" 6 "runtime/debug" 7 ) 8 9 // RecoveryHandlerLogger is an interface used by the recovering handler to print logs. 10 type RecoveryHandlerLogger interface { 11 Println(...interface{}) 12 } 13 14 type recoveryHandler struct { 15 handler http.Handler 16 logger RecoveryHandlerLogger 17 printStack bool 18 } 19 20 // RecoveryOption provides a functional approach to define 21 // configuration for a handler; such as setting the logging 22 // whether or not to print strack traces on panic. 23 type RecoveryOption func(http.Handler) 24 25 func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler { 26 for _, option := range opts { 27 option(h) 28 } 29 30 return h 31 } 32 33 // RecoveryHandler is HTTP middleware that recovers from a panic, 34 // logs the panic, writes http.StatusInternalServerError, and 35 // continues to the next handler. 36 // 37 // Example: 38 // 39 // r := mux.NewRouter() 40 // r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 41 // panic("Unexpected error!") 42 // }) 43 // 44 // http.ListenAndServe(":1123", handlers.RecoveryHandler()(r)) 45 func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler { 46 return func(h http.Handler) http.Handler { 47 r := &recoveryHandler{handler: h} 48 return parseRecoveryOptions(r, opts...) 49 } 50 } 51 52 // RecoveryLogger is a functional option to override 53 // the default logger 54 func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption { 55 return func(h http.Handler) { 56 r := h.(*recoveryHandler) 57 r.logger = logger 58 } 59 } 60 61 // PrintRecoveryStack is a functional option to enable 62 // or disable printing stack traces on panic. 63 func PrintRecoveryStack(print bool) RecoveryOption { 64 return func(h http.Handler) { 65 r := h.(*recoveryHandler) 66 r.printStack = print 67 } 68 } 69 70 func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 71 defer func() { 72 if err := recover(); err != nil { 73 w.WriteHeader(http.StatusInternalServerError) 74 h.log(err) 75 } 76 }() 77 78 h.handler.ServeHTTP(w, req) 79 } 80 81 func (h recoveryHandler) log(v ...interface{}) { 82 if h.logger != nil { 83 h.logger.Println(v...) 84 } else { 85 log.Println(v...) 86 } 87 88 if h.printStack { 89 debug.PrintStack() 90 } 91 }