@@ -5,12 +5,21 @@ import (
55 "errors"
66 "io"
77 "net/http"
8+ "reflect"
89
910 // 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"
1113 types "github.com/mutablelogic/go-server/pkg/types"
1214)
1315
16+ ///////////////////////////////////////////////////////////////////////////////
17+ // GLOBALS
18+
19+ const (
20+ FormDataMaxMemory = 256 << 20 // 256 MB
21+ )
22+
1423///////////////////////////////////////////////////////////////////////////////
1524// PUBLIC METHODS
1625
@@ -28,6 +37,8 @@ func Read(r *http.Request, v interface{}) error {
2837 return readJson (r , v )
2938 case types .ContentTypeTextPlain :
3039 return readString (r , v )
40+ case types .ContentTypeFormData :
41+ return readFormData (r , v )
3142 }
3243
3344 // Cannot handle this content type
@@ -66,3 +77,48 @@ func readString(r *http.Request, v any) error {
6677 return httpresponse .ErrInternalError .Withf ("cannot read %T as string" , v )
6778 }
6879}
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