@@ -5,12 +5,21 @@ import (
5
5
"errors"
6
6
"io"
7
7
"net/http"
8
+ "reflect"
8
9
9
10
// Packages
10
- "github.com/mutablelogic/go-server/pkg/httpresponse"
11
+ gomultipart "github.com/mutablelogic/go-client/pkg/multipart"
12
+ httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
11
13
types "github.com/mutablelogic/go-server/pkg/types"
12
14
)
13
15
16
+ ///////////////////////////////////////////////////////////////////////////////
17
+ // GLOBALS
18
+
19
+ const (
20
+ FormDataMaxMemory = 256 << 20 // 256 MB
21
+ )
22
+
14
23
///////////////////////////////////////////////////////////////////////////////
15
24
// PUBLIC METHODS
16
25
@@ -28,6 +37,8 @@ func Read(r *http.Request, v interface{}) error {
28
37
return readJson (r , v )
29
38
case types .ContentTypeTextPlain :
30
39
return readString (r , v )
40
+ case types .ContentTypeFormData :
41
+ return readFormData (r , v )
31
42
}
32
43
33
44
// Cannot handle this content type
@@ -66,3 +77,48 @@ func readString(r *http.Request, v any) error {
66
77
return httpresponse .ErrInternalError .Withf ("cannot read %T as string" , v )
67
78
}
68
79
}
80
+
81
+ var (
82
+ typeFile = reflect .TypeOf (gomultipart.File {})
83
+ )
84
+
85
+ func readFormData (r * http.Request , v any ) error {
86
+ if err := r .ParseMultipartForm (FormDataMaxMemory ); err != nil {
87
+ return err
88
+ }
89
+ if r .MultipartForm == nil {
90
+ return httpresponse .ErrBadRequest .With ("Missing form data" )
91
+ }
92
+
93
+ // Set non-file fields
94
+ if err := Query (r .MultipartForm .Value , v ); err != nil {
95
+ return err
96
+ }
97
+ // Set file fields - we only support one file per field
98
+ for key , values := range r .MultipartForm .File {
99
+ if len (values ) == 0 {
100
+ continue
101
+ }
102
+ // Get the first file for the field
103
+ value , err := writableFieldForName (v , key )
104
+ if err != nil {
105
+ return err
106
+ }
107
+ switch value .Type () {
108
+ case typeFile :
109
+ body , err := values [0 ].Open ()
110
+ if err != nil {
111
+ return errBadRequest .Withf ("cannot open file %q: %v" , values [0 ].Filename , err )
112
+ }
113
+ value .Set (reflect .ValueOf (gomultipart.File {
114
+ Path : values [0 ].Filename ,
115
+ Body : body ,
116
+ }))
117
+ default :
118
+ return httpresponse .ErrBadRequest .Withf ("cannot set field %q of type %s" , key , value .Type ())
119
+ }
120
+ }
121
+
122
+ // Return success
123
+ return nil
124
+ }
0 commit comments