forked from jackwhelpton/fasthttp-routing
-
Notifications
You must be signed in to change notification settings - Fork 1
/
panic.go
56 lines (51 loc) · 1.39 KB
/
panic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package fault
import (
"bytes"
"fmt"
"runtime"
"github.com/rmnoff/fasthttp-routing/v3"
)
// PanicHandler returns a handler that recovers from panics happened in the handlers following this one.
// When a panic is recovered, it will be converted into an error and returned to the parent handlers.
//
// A log function can be provided to log the panic call stack information. If the log function is nil,
// no message will be logged.
//
// import (
// "log"
// "github.com/rmnoff/fasthttp-routing/v3"
// "github.com/rmnoff/fasthttp-routing/v3/fault"
// )
//
// r := routing.New()
// r.Use(fault.ErrorHandler(log.Printf))
// r.Use(fault.PanicHandler(log.Printf))
func PanicHandler(logf LogFunc) routing.Handler {
return func(c *routing.Context) (err error) {
defer func() {
if e := recover(); e != nil {
if logf != nil {
logf("recovered from panic:%v", getCallStack(4))
}
var ok bool
if err, ok = e.(error); !ok {
err = fmt.Errorf("%v", e)
}
}
}()
return c.Next()
}
}
// getCallStack returns the current call stack information as a string.
// The skip parameter specifies how many top frames should be skipped.
func getCallStack(skip int) string {
buf := new(bytes.Buffer)
for i := skip; ; i++ {
_, file, line, ok := runtime.Caller(i)
if !ok {
break
}
fmt.Fprintf(buf, "\n%s:%d", file, line)
}
return buf.String()
}