| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 | 
							- package middleware
 
- import (
 
- 	"bytes"
 
- 	"io"
 
- 	"io/ioutil"
 
- 	"net/http"
 
- 	"runtime"
 
- 	"runtime/debug"
 
- 	"strings"
 
- 	"time"
 
- 	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 
- 	"github.com/gin-gonic/gin"
 
- 	"go.uber.org/zap"
 
- )
 
- type responseBodyWriter struct {
 
- 	gin.ResponseWriter
 
- 	body *bytes.Buffer
 
- }
 
- type stackErr struct {
 
- 	Err   error
 
- 	Stack string
 
- }
 
- func (s *stackErr) Error() string {
 
- 	return s.Err.Error()
 
- }
 
- func (r responseBodyWriter) Write(b []byte) (int, error) {
 
- 	r.body.Write(b)
 
- 	return r.ResponseWriter.Write(b)
 
- }
 
- // GinLogger 接管gin框架默认的日志
 
- func GinLogger() gin.HandlerFunc {
 
- 	return func(c *gin.Context) {
 
- 		// 获取 response 内容
 
- 		w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
 
- 		c.Writer = w
 
- 		var requestBody []byte
 
- 		if c.Request.Body != nil {
 
- 			requestBody, _ = ioutil.ReadAll(c.Request.Body)
 
- 			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
 
- 		}
 
- 		start := time.Now()
 
- 		c.Next()
 
- 		cost := time.Since(start)
 
- 		logFields := []zap.Field{
 
- 			zap.Int("status", c.Writer.Status()),
 
- 			zap.String("request", c.Request.Method+" "+c.Request.URL.String()),
 
- 			zap.String("query", c.Request.URL.RawQuery),
 
- 			zap.String("ip", c.ClientIP()),
 
- 			zap.String("user-agent", c.Request.UserAgent()),
 
- 			zap.String("time", cost.String()),
 
- 			zap.String("Request body", string(requestBody)),
 
- 			zap.String("Response body", w.body.String()),
 
- 		}
 
- 		if len(c.Errors) > 0 {
 
- 			logFields = append(logFields, zap.Any("stack", string(debug.Stack())))
 
- 			zaplog.Error("Http-Access-Error", logFields...)
 
- 			c.Abort()
 
- 		} else {
 
- 			zaplog.Info("Http-Access-Log", logFields...)
 
- 		}
 
- 	}
 
- }
 
- // GinRecovery recover掉我的项目可能呈现的panic
 
- func GinRecovery(stack bool) gin.HandlerFunc {
 
- 	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 {
 
- 					if se, ok := ne.Err.(*os.SyscallError); ok {
 
- 						if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
 
- 							brokenPipe = true
 
- 						}
 
- 					}
 
- 				}
 
- 				httpRequest, _ := httputil.DumpRequest(c.Request, false)
 
- 				if brokenPipe {
 
- 					zaplog.Error(c.Request.URL.Path,
 
- 						zap.Any("error", err),
 
- 						zap.String("request", string(httpRequest)),
 
- 					)
 
- 					// If the connection is dead, we can't write a status to it.
 
- 					c.Error(err.(error)) // nolint: errcheck
 
- 					c.Abort()
 
- 					return
 
- 				}
 
- 				if stack {
 
- 					zaplog.Error("[Recovery from panic]",
 
- 						zap.Any("error", err),
 
- 						zap.String("request", string(httpRequest)),
 
- 						zap.String("stack", string(debug.Stack())),
 
- 					)
 
- 				} else {
 
- 					zaplog.Error("[Recovery from panic]",
 
- 						zap.Any("error", err),
 
- 						zap.String("request", string(httpRequest)),
 
- 					)
 
- 				}*/
 
- 				defer func() {
 
- 					if err = recover(); err != nil {
 
- 						body, _ := ioutil.ReadAll(c.Request.Body)
 
- 						// 获取 panic 发生的位置
 
- 						pc, file, line, ok := runtime.Caller(2)
 
- 						funcName := ""
 
- 						if ok {
 
- 							fn := runtime.FuncForPC(pc).Name()
 
- 							// 去除包路径,只保留函数名
 
- 							/*funcName = filepath.Base(fn)
 
- 							file = filepath.Base(file)*/
 
- 							parts := strings.Split(fn, "/")
 
- 							if len(parts) > 0 {
 
- 								lastPart := parts[len(parts)-1]
 
- 								parts = strings.Split(lastPart, ".")
 
- 								if len(parts) > 0 {
 
- 									funcName = parts[len(parts)-1]
 
- 								}
 
- 							}
 
- 							file = strings.TrimPrefix(file, c.Request.Context().Value(gin.ContextKey).(string)+"/") // 尝试去除项目路径前缀(可选)
 
- 						}
 
- 						zaplog.Error("cors",
 
- 							zap.Any("recover", err),
 
- 							zap.Any("url", c.Request.URL),
 
- 							zap.Any("file", file),
 
- 							zap.Any("line", line),
 
- 							zap.Any("func", funcName),
 
- 							zap.Any("request", string(body)),
 
- 						)
 
- 						c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
 
- 					}
 
- 				}()
 
- 				c.AbortWithStatus(http.StatusInternalServerError)
 
- 			}
 
- 		}()
 
- 		c.Next()
 
- 	}
 
- }
 
 
  |