116 lines
2.5 KiB
Go
116 lines
2.5 KiB
Go
package utils
|
|
|
|
import (
|
|
"mime/multipart"
|
|
"strings"
|
|
|
|
"github.com/goccy/go-json"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
func ParseForm(ctx *fasthttp.RequestCtx) (map[string]any, error) {
|
|
contentType := string(ctx.Request.Header.ContentType())
|
|
formData := make(map[string]any)
|
|
|
|
switch {
|
|
case strings.Contains(contentType, "multipart/form-data"):
|
|
if err := parseMultipartInto(ctx, formData); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
case strings.Contains(contentType, "application/x-www-form-urlencoded"):
|
|
args := ctx.PostArgs()
|
|
args.VisitAll(func(key, value []byte) {
|
|
appendValue(formData, string(key), string(value))
|
|
})
|
|
|
|
case strings.Contains(contentType, "application/json"):
|
|
if err := json.Unmarshal(ctx.PostBody(), &formData); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
default:
|
|
// Leave formData empty if content-type is unrecognized
|
|
}
|
|
|
|
return formData, nil
|
|
}
|
|
|
|
func parseMultipartInto(ctx *fasthttp.RequestCtx, formData map[string]any) error {
|
|
form, err := ctx.MultipartForm()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for key, values := range form.Value {
|
|
if len(values) == 1 {
|
|
formData[key] = values[0]
|
|
} else if len(values) > 1 {
|
|
formData[key] = values
|
|
}
|
|
}
|
|
|
|
if len(form.File) > 0 {
|
|
files := make(map[string]any, len(form.File))
|
|
for fieldName, fileHeaders := range form.File {
|
|
if len(fileHeaders) == 1 {
|
|
files[fieldName] = fileInfoToMap(fileHeaders[0])
|
|
} else {
|
|
fileInfos := make([]map[string]any, len(fileHeaders))
|
|
for i, fh := range fileHeaders {
|
|
fileInfos[i] = fileInfoToMap(fh)
|
|
}
|
|
files[fieldName] = fileInfos
|
|
}
|
|
}
|
|
formData["_files"] = files
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func appendValue(formData map[string]any, key, value string) {
|
|
if existing, exists := formData[key]; exists {
|
|
switch v := existing.(type) {
|
|
case string:
|
|
formData[key] = []string{v, value}
|
|
case []string:
|
|
formData[key] = append(v, value)
|
|
}
|
|
} else {
|
|
formData[key] = value
|
|
}
|
|
}
|
|
|
|
func fileInfoToMap(fh *multipart.FileHeader) map[string]any {
|
|
ct := fh.Header.Get("Content-Type")
|
|
if ct == "" {
|
|
ct = getMimeType(fh.Filename)
|
|
}
|
|
|
|
return map[string]any{
|
|
"filename": fh.Filename,
|
|
"size": fh.Size,
|
|
"mimetype": ct,
|
|
}
|
|
}
|
|
|
|
func getMimeType(filename string) string {
|
|
if i := strings.LastIndex(filename, "."); i >= 0 {
|
|
switch filename[i:] {
|
|
case ".pdf":
|
|
return "application/pdf"
|
|
case ".png":
|
|
return "image/png"
|
|
case ".jpg", ".jpeg":
|
|
return "image/jpeg"
|
|
case ".gif":
|
|
return "image/gif"
|
|
case ".svg":
|
|
return "image/svg+xml"
|
|
}
|
|
}
|
|
return "application/octet-stream"
|
|
}
|