-
Notifications
You must be signed in to change notification settings - Fork 0
/
form.go
141 lines (130 loc) · 3.94 KB
/
form.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package requests
import (
"fmt"
"io"
"net/url"
"strings"
"github.com/google/go-querystring/query"
)
// File represents a form file
type File struct {
Name string // Form field name
FileName string // File name
Content io.ReadCloser // File content
}
// SetContent sets the content of the file
func (f *File) SetContent(content io.ReadCloser) {
f.Content = content
}
// SetFileName sets the file name
func (f *File) SetFileName(fileName string) {
f.FileName = fileName
}
// SetName sets the form field name
func (f *File) SetName(name string) {
f.Name = name
}
// parseFormFields parses the given form fields into url.Values.
func parseFormFields(fields any) (url.Values, error) {
switch data := fields.(type) {
case url.Values:
// Directly return url.Values data.
return data, nil
case map[string][]string:
// Convert and return map[string][]string data as url.Values.
return url.Values(data), nil
case map[string]string:
// Convert and return map[string]string data as url.Values.
values := make(url.Values)
for key, value := range data {
values.Set(key, value)
}
return values, nil
default:
// Attempt to use query.Values for encoding struct types.
if values, err := query.Values(fields); err == nil {
return values, nil
} else {
// Return an error if encoding fails or type is unsupported.
return nil, fmt.Errorf("%w: %v", ErrUnsupportedFormFieldsType, err) //nolint:errorlint
}
}
}
// parseForm parses the given form data into url.Values and []*File.
func parseForm(v any) (url.Values, []*File, error) {
switch data := v.(type) {
case url.Values:
// Directly return url.Values data.
return data, nil, nil
case map[string][]string:
// Convert and return map[string][]string data as url.Values.
return url.Values(data), nil, nil
case map[string]string:
// Convert and return map[string]string data as url.Values.
values := make(url.Values)
for key, value := range data {
values.Set(key, value)
}
return values, nil, nil
case map[string]any:
// Convert and return map[string]any data as url.Values and []*File.
values := make(url.Values)
files := make([]*File, 0)
for key, value := range data {
switch v := value.(type) {
case string:
values.Set(key, v)
case []string:
for _, v := range v {
values.Add(key, v)
}
case *File:
v.SetName(key)
files = append(files, v)
default:
// Return an error if type is unsupported.
return nil, nil, fmt.Errorf("%w: %T", ErrUnsupportedDataType, value)
}
}
return values, files, nil
default:
// Attempt to use query.Values for encoding struct types.
if values, err := query.Values(v); err == nil {
return values, nil, nil
} else {
// Return an error if encoding fails or type is unsupported.
return nil, nil, fmt.Errorf("%w: %v", ErrUnsupportedFormFieldsType, err) //nolint:errorlint
}
}
}
// FormEncoder handles encoding of form data.
type FormEncoder struct{}
// Encode encodes the given value into URL-encoded form data.
func (e *FormEncoder) Encode(v any) (io.Reader, error) {
switch data := v.(type) {
case url.Values:
// Directly encode url.Values data.
return strings.NewReader(data.Encode()), nil
case map[string][]string:
// Convert and encode map[string][]string data as url.Values.
values := url.Values(data)
return strings.NewReader(values.Encode()), nil
case map[string]string:
// Convert and encode map[string]string data as url.Values.
values := make(url.Values)
for key, value := range data {
values.Set(key, value)
}
return strings.NewReader(values.Encode()), nil
default:
// Attempt to use query.Values for encoding struct types.
if values, err := query.Values(v); err == nil {
return strings.NewReader(values.Encode()), nil
} else {
// Return an error if encoding fails or type is unsupported.
return nil, fmt.Errorf("%w: %v", ErrEncodingFailed, err) //nolint:errorlint
}
}
}
// DefaultFormEncoder instance
var DefaultFormEncoder = &FormEncoder{}