| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 | package middlewareimport (	"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掉我的项目可能呈现的panicfunc 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()	}}
 |