mirror of
https://github.com/kataras/iris.git
synced 2025-12-23 12:57:05 +00:00
minor improvements
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"net/http/httputil"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12/context"
|
||||
)
|
||||
@@ -15,65 +14,76 @@ func init() {
|
||||
context.SetHandlerName("iris/middleware/recover.*", "iris.recover")
|
||||
}
|
||||
|
||||
func getRequestLogs(ctx *context.Context) string {
|
||||
rawReq, _ := httputil.DumpRequest(ctx.Request(), false)
|
||||
return string(rawReq)
|
||||
}
|
||||
|
||||
// New returns a new recover middleware,
|
||||
// it recovers from panics and logs
|
||||
// the panic message to the application's logger "Warn" level.
|
||||
// New returns a new recovery middleware,
|
||||
// it recovers from panics and logs the
|
||||
// panic message to the application's logger "Warn" level.
|
||||
func New() context.Handler {
|
||||
return func(ctx *context.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if ctx.IsStopped() { // handled by other middleware.
|
||||
return
|
||||
}
|
||||
|
||||
var callers []string
|
||||
for i := 1; ; i++ {
|
||||
_, file, line, got := runtime.Caller(i)
|
||||
if !got {
|
||||
break
|
||||
}
|
||||
|
||||
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
||||
}
|
||||
|
||||
// when stack finishes
|
||||
logMessage := fmt.Sprintf("Recovered from a route's Handler('%s')\n", ctx.HandlerName())
|
||||
logMessage += fmt.Sprint(getRequestLogs(ctx))
|
||||
logMessage += fmt.Sprintf("%s\n", err)
|
||||
logMessage += fmt.Sprintf("%s\n", strings.Join(callers, "\n"))
|
||||
ctx.Application().Logger().Warn(logMessage)
|
||||
|
||||
// get the list of registered handlers and the
|
||||
// handler which panic derived from.
|
||||
handlers := ctx.Handlers()
|
||||
handlersFileLines := make([]string, 0, len(handlers))
|
||||
currentHandlerIndex := ctx.HandlerIndex(-1)
|
||||
currentHandlerFileLine := "???"
|
||||
for i, h := range ctx.Handlers() {
|
||||
file, line := context.HandlerFileLine(h)
|
||||
fileline := fmt.Sprintf("%s:%d", file, line)
|
||||
handlersFileLines = append(handlersFileLines, fileline)
|
||||
if i == currentHandlerIndex {
|
||||
currentHandlerFileLine = fileline
|
||||
}
|
||||
}
|
||||
|
||||
// see accesslog.wasRecovered too.
|
||||
ctx.StopWithPlainError(500, &context.ErrPanicRecovery{
|
||||
Cause: err,
|
||||
Callers: callers,
|
||||
Stack: debug.Stack(),
|
||||
RegisteredHandlers: handlersFileLines,
|
||||
CurrentHandler: currentHandlerFileLine,
|
||||
})
|
||||
}
|
||||
if err := PanicRecoveryError(ctx, recover()); err != nil {
|
||||
ctx.StopWithPlainError(500, err)
|
||||
ctx.Application().Logger().Warn(err.LogMessage())
|
||||
} // else it's already handled.
|
||||
}()
|
||||
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// PanicRecoveryError returns a new ErrPanicRecovery error.
|
||||
func PanicRecoveryError(ctx *context.Context, err any) *context.ErrPanicRecovery {
|
||||
if recoveryErr, ok := ctx.IsRecovered(); ok {
|
||||
// If registered before any other recovery middleware, get its error.
|
||||
// Because of defer this will be executed last, after the recovery middleware in this case.
|
||||
return recoveryErr
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
} else if ctx.IsStopped() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var callers []string
|
||||
for i := 2; ; /* 1 for New() 2 for NewPanicRecoveryError */ i++ {
|
||||
_, file, line, got := runtime.Caller(i)
|
||||
if !got {
|
||||
break
|
||||
}
|
||||
|
||||
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
||||
}
|
||||
|
||||
// get the list of registered handlers and the
|
||||
// handler which panic derived from.
|
||||
handlers := ctx.Handlers()
|
||||
handlersFileLines := make([]string, 0, len(handlers))
|
||||
currentHandlerIndex := ctx.HandlerIndex(-1)
|
||||
currentHandlerFileLine := "???"
|
||||
for i, h := range ctx.Handlers() {
|
||||
file, line := context.HandlerFileLine(h)
|
||||
fileline := fmt.Sprintf("%s:%d", file, line)
|
||||
handlersFileLines = append(handlersFileLines, fileline)
|
||||
if i == currentHandlerIndex {
|
||||
currentHandlerFileLine = fileline
|
||||
}
|
||||
}
|
||||
|
||||
// see accesslog.wasRecovered too.
|
||||
recoveryErr := &context.ErrPanicRecovery{
|
||||
Cause: err,
|
||||
Callers: callers,
|
||||
Stack: debug.Stack(),
|
||||
RegisteredHandlers: handlersFileLines,
|
||||
CurrentHandlerFileLine: currentHandlerFileLine,
|
||||
CurrentHandlerName: ctx.HandlerName(),
|
||||
Request: getRequestLogs(ctx),
|
||||
}
|
||||
|
||||
return recoveryErr
|
||||
}
|
||||
|
||||
func getRequestLogs(ctx *context.Context) string {
|
||||
rawReq, _ := httputil.DumpRequest(ctx.Request(), false)
|
||||
return string(rawReq)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user