智盟项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

58 lines
1.3 KiB

  1. package mw
  2. import (
  3. "net"
  4. "net/http"
  5. "net/http/httputil"
  6. "os"
  7. "runtime/debug"
  8. "strings"
  9. "github.com/gin-gonic/gin"
  10. "go.uber.org/zap"
  11. )
  12. func Recovery(logger *zap.Logger, stack bool) gin.HandlerFunc {
  13. return func(c *gin.Context) {
  14. defer func() {
  15. if err := recover(); err != nil {
  16. var brokenPipe bool
  17. if ne, ok := err.(*net.OpError); ok {
  18. if se, ok := ne.Err.(*os.SyscallError); ok {
  19. if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
  20. brokenPipe = true
  21. }
  22. }
  23. }
  24. httpRequest, _ := httputil.DumpRequest(c.Request, false)
  25. if brokenPipe {
  26. logger.Error(c.Request.URL.Path,
  27. zap.Any("error", err),
  28. zap.String("request", string(httpRequest)),
  29. )
  30. // If the connection is dead, we can't write a status to it.
  31. c.Error(err.(error))
  32. c.Abort()
  33. return
  34. }
  35. if stack {
  36. logger.Error("[Recovery from panic]",
  37. zap.Any("error", err),
  38. zap.String("request", string(httpRequest)),
  39. zap.String("stack", string(debug.Stack())),
  40. )
  41. } else {
  42. logger.Error("[Recovery from panic]",
  43. zap.Any("error", err),
  44. zap.String("request", string(httpRequest)),
  45. )
  46. }
  47. c.AbortWithStatus(http.StatusInternalServerError)
  48. }
  49. }()
  50. c.Next()
  51. }
  52. }