recovery.go 928 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package tango
  2. import (
  3. "fmt"
  4. "net/http"
  5. "runtime"
  6. )
  7. type Recovery struct {
  8. debug bool
  9. logger Logger
  10. }
  11. func (recovery *Recovery) SetLogger(logger Logger) {
  12. recovery.logger = logger
  13. }
  14. func NewRecovery(debug bool) *Recovery {
  15. return &Recovery{debug: debug}
  16. }
  17. func (recovery *Recovery) Handle(ctx *Context) {
  18. defer func() {
  19. if e := recover(); e != nil {
  20. content := fmt.Sprintf("Handler crashed with error: %v", e)
  21. for i := 1; ;i += 1 {
  22. _, file, line, ok := runtime.Caller(i)
  23. if !ok {
  24. break
  25. } else {
  26. content += "\n"
  27. }
  28. content += fmt.Sprintf("%v %v", file, line)
  29. }
  30. if recovery.logger != nil {
  31. recovery.logger.Error(content)
  32. }
  33. if !ctx.Written() {
  34. ctx.WriteHeader(http.StatusInternalServerError)
  35. if !recovery.debug {
  36. content = http.StatusText(http.StatusInternalServerError)
  37. }
  38. ctx.Write([]byte(content))
  39. }
  40. }
  41. }()
  42. ctx.Next()
  43. }