Merge pull request #2235 from seefs001/fix/boundary-parser-error

fix: boundary parser error (error parsing multipart NextPart: bufio: buffer full)
This commit is contained in:
Calcium-Ion
2025-11-16 14:12:46 +08:00
committed by GitHub
+41 -12
View File
@@ -2,7 +2,9 @@ package common
import ( import (
"bytes" "bytes"
"errors"
"io" "io"
"mime"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
@@ -128,13 +130,13 @@ func ParseMultipartFormReusable(c *gin.Context) (*multipart.Form, error) {
} }
contentType := c.Request.Header.Get("Content-Type") contentType := c.Request.Header.Get("Content-Type")
boundary := "" boundary, err := parseBoundary(contentType)
if idx := strings.Index(contentType, "boundary="); idx != -1 { if err != nil {
boundary = contentType[idx+9:] return nil, err
} }
reader := multipart.NewReader(bytes.NewReader(requestBody), boundary) reader := multipart.NewReader(bytes.NewReader(requestBody), boundary)
form, err := reader.ReadForm(32 << 20) // 32 MB max memory form, err := reader.ReadForm(multipartMemoryLimit())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -177,17 +179,16 @@ func parseFormData(data []byte, v any) error {
func parseMultipartFormData(c *gin.Context, data []byte, v any) error { func parseMultipartFormData(c *gin.Context, data []byte, v any) error {
contentType := c.Request.Header.Get("Content-Type") contentType := c.Request.Header.Get("Content-Type")
boundary := "" boundary, err := parseBoundary(contentType)
if idx := strings.Index(contentType, "boundary="); idx != -1 { if err != nil {
boundary = contentType[idx+9:] if errors.Is(err, errBoundaryNotFound) {
} return Unmarshal(data, v) // Fallback to JSON
}
if boundary == "" { return err
return Unmarshal(data, v) // Fallback to JSON
} }
reader := multipart.NewReader(bytes.NewReader(data), boundary) reader := multipart.NewReader(bytes.NewReader(data), boundary)
form, err := reader.ReadForm(32 << 20) // 32 MB max memory form, err := reader.ReadForm(multipartMemoryLimit())
if err != nil { if err != nil {
return err return err
} }
@@ -203,3 +204,31 @@ func parseMultipartFormData(c *gin.Context, data []byte, v any) error {
return processFormMap(formMap, v) return processFormMap(formMap, v)
} }
var errBoundaryNotFound = errors.New("multipart boundary not found")
// parseBoundary extracts the multipart boundary from the Content-Type header using mime.ParseMediaType
func parseBoundary(contentType string) (string, error) {
if contentType == "" {
return "", errBoundaryNotFound
}
// Boundary-UUID / boundary-------xxxxxx
_, params, err := mime.ParseMediaType(contentType)
if err != nil {
return "", err
}
boundary, ok := params["boundary"]
if !ok || boundary == "" {
return "", errBoundaryNotFound
}
return boundary, nil
}
// multipartMemoryLimit returns the configured multipart memory limit in bytes
func multipartMemoryLimit() int64 {
limitMB := constant.MaxFileDownloadMB
if limitMB <= 0 {
limitMB = 32
}
return int64(limitMB) << 20
}