golib/middleware/recover_log.go

75 lines
1.9 KiB
Go
Raw Normal View History

2023-06-15 21:22:51 +08:00
//
// recover_log.go
// Copyright (C) 2022 tiglog <me@tiglog.com>
//
// Distributed under terms of the MIT license.
//
package middleware
import (
2023-08-12 20:03:19 +08:00
"errors"
2023-06-15 21:22:51 +08:00
"net"
"net/http"
"net/http/httputil"
"os"
"strings"
2023-08-12 20:03:19 +08:00
"time"
2023-06-15 21:22:51 +08:00
2023-06-15 21:38:12 +08:00
"git.hexq.cn/tiglog/golib/logger"
2023-07-15 17:52:50 +08:00
"github.com/gin-gonic/gin"
2023-06-15 21:22:51 +08:00
)
2023-08-12 20:03:19 +08:00
func GinRecover(logfile string) gin.HandlerFunc {
log := logger.New(logger.NewProductionRotateBySize(logfile), logger.ErrorLevel)
defer log.Sync()
2023-06-15 21:22:51 +08:00
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace.
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
2023-08-12 20:03:19 +08:00
var se *os.SyscallError
if errors.As(ne, &se) {
seStr := strings.ToLower(se.Error())
if strings.Contains(seStr, "broken pipe") ||
strings.Contains(seStr, "connection reset by peer") {
2023-06-15 21:22:51 +08:00
brokenPipe = true
}
}
}
httpRequest, _ := httputil.DumpRequest(c.Request, false)
2023-08-12 20:03:19 +08:00
headers := strings.Split(string(httpRequest), "\r\n")
for idx, header := range headers {
current := strings.Split(header, ":")
if current[0] == "Authorization" {
headers[idx] = current[0] + ": *"
}
}
headersToStr := strings.Join(headers, "\r\n")
2023-06-15 21:22:51 +08:00
if brokenPipe {
2023-08-12 20:03:19 +08:00
log.Error(c.Request.URL.String(),
logger.Any("err", err),
logger.String("headers", headersToStr),
logger.Stack("stack"),
)
2023-06-15 21:22:51 +08:00
// If the connection is dead, we can't write a status to it.
c.Error(err.(error)) // nolint: errcheck
c.Abort()
2023-08-12 20:03:19 +08:00
} else {
log.Error(c.Request.URL.String(),
logger.Any("err", err),
logger.String("headers", headersToStr),
logger.Stack("stack"),
logger.String("panicRecoveredTime", time.Now().Format(time.RFC3339)),
)
c.AbortWithStatus(http.StatusInternalServerError)
2023-06-15 21:22:51 +08:00
}
}
}()
c.Next()
}
}