60 lines
1.1 KiB
Go
Raw Normal View History

2019-06-01 04:55:49 +00:00
package middleware
import (
"fmt"
"net/http"
2019-06-03 05:53:04 +00:00
"os"
2019-06-01 04:55:49 +00:00
"runtime"
2019-06-03 05:53:04 +00:00
"strings"
2019-06-01 04:55:49 +00:00
"github.com/aerogo/aero"
2019-11-04 07:34:00 +00:00
"github.com/animenotifier/notify.moe/arn"
2019-06-01 04:55:49 +00:00
)
// Recover recovers from panics and shows them as the response body.
func Recover(next aero.Handler) aero.Handler {
return func(ctx aero.Context) error {
defer func() {
r := recover()
if r == nil {
return
}
err, ok := r.(error)
if !ok {
err = fmt.Errorf("%v", r)
}
stack := make([]byte, 4096)
2019-11-04 07:34:00 +00:00
length := runtime.Stack(stack, false)
2019-06-03 05:53:04 +00:00
stackString := string(stack[:length])
fmt.Fprint(os.Stderr, stackString)
2019-11-04 07:34:00 +00:00
// Save crash in database
crash := &arn.Crash{
Error: err.Error(),
Stack: stackString,
2019-11-04 08:08:47 +00:00
Path: ctx.Path(),
2019-11-04 07:34:00 +00:00
}
crash.ID = arn.GenerateID("Crash")
crash.Created = arn.DateTimeUTC()
user := arn.GetUserFromContext(ctx)
if user != nil {
crash.CreatedBy = user.ID
}
crash.Save()
// Send HTML
message := "<div class='crash'>" + err.Error() + "<br><br>" + strings.ReplaceAll(stackString, "\n", "<br>") + "</div>"
2019-06-03 05:53:04 +00:00
_ = ctx.Error(http.StatusInternalServerError, message)
2019-06-01 04:55:49 +00:00
}()
return next(ctx)
}
}