优化
This commit is contained in:
@@ -2,17 +2,22 @@ package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"kra/internal/biz"
|
||||
"kra/internal/conf"
|
||||
"kra/internal/server/httpx"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const defaultRequestBodyLimit int64 = 8 << 20
|
||||
|
||||
// AccessLog is the single global request/response capture point, matching
|
||||
// the reference middleware ordering and making every HTTP request observable.
|
||||
func AccessLog(runtime *conf.Runtime, logger *slog.Logger, version string) gin.HandlerFunc {
|
||||
@@ -20,20 +25,45 @@ func AccessLog(runtime *conf.Runtime, logger *slog.Logger, version string) gin.H
|
||||
started := time.Now()
|
||||
var requestBody []byte
|
||||
multipart := strings.Contains(c.GetHeader("Content-Type"), "multipart/form-data")
|
||||
mediaUpload := multipart && isMediaUploadRoute(c.FullPath())
|
||||
config := runtime.Admin()
|
||||
bodyLimit := defaultRequestBodyLimit
|
||||
if mediaUpload {
|
||||
bodyLimit = biz.DefaultMaxMediaFileSize + (1 << 20)
|
||||
if config != nil && config.Media != nil && config.Media.MaxFileSize > 0 {
|
||||
bodyLimit = config.Media.MaxFileSize + (1 << 20)
|
||||
}
|
||||
}
|
||||
bytesIn := c.Request.ContentLength
|
||||
if c.Request.Body != nil && !multipart {
|
||||
requestBody, _ = io.ReadAll(c.Request.Body)
|
||||
c.Request.Body = io.NopCloser(bytes.NewReader(requestBody))
|
||||
bytesIn = int64(len(requestBody))
|
||||
}
|
||||
if bytesIn < 0 {
|
||||
bytesIn = 0
|
||||
}
|
||||
maxBytes := 1 << 20
|
||||
writer := &captureWriter{ResponseWriter: c.Writer, maxBytes: maxBytes}
|
||||
c.Writer = writer
|
||||
c.Header("X-Kra-Version", version)
|
||||
config := runtime.Admin()
|
||||
requestReadFailed := c.Request.ContentLength > bodyLimit
|
||||
if requestReadFailed {
|
||||
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, gin.H{"code": httpx.CodeError, "msg": "请求体超过大小上限"})
|
||||
} else if c.Request.Body != nil && !mediaUpload {
|
||||
limited := http.MaxBytesReader(c.Writer, c.Request.Body, bodyLimit)
|
||||
var err error
|
||||
requestBody, err = io.ReadAll(limited)
|
||||
if err != nil {
|
||||
requestReadFailed = true
|
||||
var tooLarge *http.MaxBytesError
|
||||
if errors.As(err, &tooLarge) {
|
||||
c.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, gin.H{"code": httpx.CodeError, "msg": "请求体超过大小上限"})
|
||||
} else {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"code": httpx.CodeError, "msg": "请求体读取失败"})
|
||||
}
|
||||
} else {
|
||||
c.Request.Body = io.NopCloser(bytes.NewReader(requestBody))
|
||||
bytesIn = int64(len(requestBody))
|
||||
}
|
||||
} else if c.Request.Body != nil {
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, bodyLimit)
|
||||
}
|
||||
if bytesIn < 0 {
|
||||
bytesIn = 0
|
||||
}
|
||||
logLimit := 1024
|
||||
if config != nil && config.Zap != nil && config.Zap.AccessLogMaxBytes > 0 {
|
||||
logLimit = int(config.Zap.AccessLogMaxBytes)
|
||||
@@ -46,7 +76,9 @@ func AccessLog(runtime *conf.Runtime, logger *slog.Logger, version string) gin.H
|
||||
}
|
||||
c.Set(ctxReqBodyKey, requestText)
|
||||
c.Set(ctxRespBufferKey, &writer.body)
|
||||
c.Next()
|
||||
if !requestReadFailed {
|
||||
c.Next()
|
||||
}
|
||||
if logger == nil {
|
||||
return
|
||||
}
|
||||
@@ -86,6 +118,11 @@ func AccessLog(runtime *conf.Runtime, logger *slog.Logger, version string) gin.H
|
||||
}
|
||||
}
|
||||
|
||||
func isMediaUploadRoute(route string) bool {
|
||||
return strings.HasSuffix(route, "/fileUploadAndDownload/upload") ||
|
||||
strings.HasSuffix(route, "/mediaUpload/chunk")
|
||||
}
|
||||
|
||||
func redactHeaders(headers map[string][]string) map[string]string {
|
||||
out := make(map[string]string, len(headers))
|
||||
for key, values := range headers {
|
||||
|
||||
Reference in New Issue
Block a user