سلام وقت بخیر
خیلی ممنون بابت پاسخ هاتون به سوالات بنده در دروس فصلهای قبلی
چند تا سوال از کدهای زیر داشتم ؟
type bodyLogWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (w bodyLogWriter) Write(b []byte) (int, error) {
w.body.Write(b)
return w.ResponseWriter.Write(b)
}
func (w bodyLogWriter) WriteString(s string) (int, error) {
w.body.WriteString(s)
return w.ResponseWriter.WriteString(s)
}
func DefaultStructuredLogger(cfg *config.Config) gin.HandlerFunc {
logger := logging.NewLogger(cfg)
return structuredLogger(logger)
}
func structuredLogger(logger logging.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
if strings.Contains(c.FullPath(), "swagger") {
c.Next()
} else {
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
start := time.Now() // start
path := c.FullPath()
raw := c.Request.URL.RawQuery
bodyBytes, _ := io.ReadAll(c.Request.Body)
c.Request.Body.Close()
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
c.Writer = blw
c.Next()
param := gin.LogFormatterParams{}
param.TimeStamp = time.Now() // stop
param.Latency = param.TimeStamp.Sub(start)
param.ClientIP = c.ClientIP()
param.Method = c.Request.Method
param.StatusCode = c.Writer.Status()
param.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()
param.BodySize = c.Writer.Size()
if raw != "" {
path = path + "?" + raw
}
param.Path = path
keys := map[logging.ExtraKey]interface{}{}
keys[logging.Path] = param.Path
keys[logging.ClientIp] = param.ClientIP
keys[logging.Method] = param.Method
keys[logging.Latency] = param.Latency
keys[logging.StatusCode] = param.StatusCode
keys[logging.ErrorMessage] = param.ErrorMessage
keys[logging.BodySize] = param.BodySize
keys[logging.RequestBody] = string(bodyBytes)
keys[logging.ResponseBody] = blw.body.String()
logger.Info(logging.RequestResponse, logging.Api, "", keys)
}
}
}
در آموزش اگفیتد ResponseWriter مسئول نوشتن در RespnoseBody میباشد در کد زیر چرا مقدار blw را در c.Writer قرار میگیرد ؟ منظورم این هست که Writer مربوط به Contex چه نقشی دارد ، که باید قبل از c.Next() باید مقدار دهیی شود
2- در کد زیر چرا c.Request.Body بعد از خوانده شدن باید close شود ؟
bodyBytes, _ := io.ReadAll(c.Request.Body)
c.Request.Body.Close()
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
و اینکه چرا دوباره c.Request.Body باید مقدار دهی شود ؟ و کاربر NopCloser را متوجه نشدم
3- متدهای WriteString و Write چه زمانی call میشوند تا فیلد body بتواند پر شود ؟