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:
+41
-12
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user