feat: http support print body log (#1757)

* add log
This commit is contained in:
Yening Qin 2023-10-24 11:37:34 +08:00 committed by GitHub
parent 314a8d71ef
commit d52848ab1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 23 deletions

View File

@ -167,8 +167,10 @@ func (rt *Router) dsProxy(c *gin.Context) {
modifyResponse := func(r *http.Response) error {
if r.StatusCode == http.StatusUnauthorized {
logger.Warningf("proxy path:%s unauthorized access ", c.Request.URL.Path)
return fmt.Errorf("unauthorized access")
}
return nil
}
@ -180,6 +182,7 @@ func (rt *Router) dsProxy(c *gin.Context) {
}
proxy.ServeHTTP(c.Writer, c.Request)
}
var (

View File

@ -2,6 +2,7 @@ package aop
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"net/http"
@ -40,7 +41,8 @@ type LoggerConfig struct {
// Output is a writer where logs are written.
// Optional. Default value is gin.DefaultWriter.
Output io.Writer
Output io.Writer
PrintBody bool
// SkipPaths is a url path array which logs are not written.
// Optional.
@ -177,8 +179,13 @@ func ErrorLoggerT(typ gin.ErrorType) gin.HandlerFunc {
// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter.
// By default gin.DefaultWriter = os.Stdout.
func Logger() gin.HandlerFunc {
return LoggerWithConfig(LoggerConfig{})
func Logger(conf ...LoggerConfig) gin.HandlerFunc {
var configuration LoggerConfig
if len(conf) > 0 {
configuration = conf[0]
}
return LoggerWithConfig(configuration)
}
// LoggerWithFormatter instance a Logger middleware with the specified log format function.
@ -197,6 +204,21 @@ func LoggerWithWriter(out io.Writer, notlogged ...string) gin.HandlerFunc {
})
}
type CustomResponseWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w CustomResponseWriter) Write(data []byte) (int, error) {
w.body.Write(data)
return w.ResponseWriter.Write(data)
}
func (w CustomResponseWriter) WriteString(s string) (int, error) {
w.body.WriteString(s)
return w.ResponseWriter.WriteString(s)
}
// LoggerWithConfig instance a Logger middleware with config.
func LoggerWithConfig(conf LoggerConfig) gin.HandlerFunc {
formatter := conf.Formatter
@ -234,18 +256,24 @@ func LoggerWithConfig(conf LoggerConfig) gin.HandlerFunc {
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
// var (
// rdr1 io.ReadCloser
// rdr2 io.ReadCloser
// )
var (
rdr1 io.ReadCloser
rdr2 io.ReadCloser
)
// if c.Request.Method != "GET" {
// buf, _ := ioutil.ReadAll(c.Request.Body)
// rdr1 = ioutil.NopCloser(bytes.NewBuffer(buf))
// rdr2 = ioutil.NopCloser(bytes.NewBuffer(buf))
bodyWriter := &CustomResponseWriter{
ResponseWriter: c.Writer,
body: bytes.NewBuffer(nil),
}
c.Writer = bodyWriter
// c.Request.Body = rdr2
// }
if conf.PrintBody {
buf, _ := io.ReadAll(c.Request.Body)
rdr1 = io.NopCloser(bytes.NewBuffer(buf))
rdr2 = io.NopCloser(bytes.NewBuffer(buf))
c.Request.Body = rdr2
}
// Process request
c.Next()
@ -277,18 +305,36 @@ func LoggerWithConfig(conf LoggerConfig) gin.HandlerFunc {
// fmt.Fprint(out, formatter(param))
logger.Info(formatter(param))
// if c.Request.Method != "GET" {
// logger.Debug(readBody(rdr1))
// }
if conf.PrintBody {
respBody := readBody(bytes.NewReader(bodyWriter.body.Bytes()), c.Writer.Header().Get("Content-Encoding"))
reqBody := readBody(rdr1, c.Request.Header.Get("Content-Encoding"))
logger.Debugf("path:%s req body:%s resp:%s", path, reqBody, respBody)
}
}
}
}
func readBody(reader io.Reader) string {
buf := new(bytes.Buffer)
buf.ReadFrom(reader)
func readBody(reader io.Reader, encoding string) string {
var bodyBytes []byte
var err error
s := buf.String()
return s
if encoding == "gzip" {
gzipReader, err := gzip.NewReader(reader)
if err != nil {
return fmt.Sprintf("failed to create gzip reader: %v", err)
}
defer gzipReader.Close()
bodyBytes, err = io.ReadAll(gzipReader)
if err != nil {
return fmt.Sprintf("failed to read gzip response body: %v", err)
}
} else {
bodyBytes, err = io.ReadAll(reader)
if err != nil {
return fmt.Sprintf("failed to read response body: %v", err)
}
}
return string(bodyBytes)
}

View File

@ -24,6 +24,7 @@ type Config struct {
KeyFile string
PProf bool
PrintAccessLog bool
PrintBody bool
ExposeMetrics bool
ShutdownTimeout int
MaxContentLength int64
@ -72,7 +73,7 @@ type JWTAuth struct {
func GinEngine(mode string, cfg Config) *gin.Engine {
gin.SetMode(mode)
loggerMid := aop.Logger()
loggerMid := aop.Logger(aop.LoggerConfig{PrintBody: cfg.PrintBody})
recoveryMid := aop.Recovery()
if strings.ToLower(mode) == "release" {