| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 | package middlewareimport (	"bytes"	"io/ioutil"	"net"	"net/http"	"net/http/httputil"	"os"	"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}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("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),			zap.String("time", cost.String()),			zap.String("x-request-id", c.Request.Header.Get("X-Request-Id")),		}		logFields = append(logFields, zap.String("Request body", string(requestBody)))		logFields = append(logFields, zap.String("Response body", w.body.String()))		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)),					)				}				c.AbortWithStatus(http.StatusInternalServerError)			}		}()		c.Next()	}}
 |