1
1
package web
2
2
3
3
import (
4
+ "bytes"
4
5
"container/vector"
5
6
"fmt"
6
7
"http"
@@ -25,6 +26,7 @@ type Request struct {
25
26
UserAgent string
26
27
Params map [string ][]string
27
28
Cookies map [string ]string
29
+ Files map [string ][]byte
28
30
}
29
31
30
32
type badStringError struct {
@@ -144,7 +146,58 @@ func (r *Request) ParseParams() (err os.Error) {
144
146
return err
145
147
}
146
148
query = string (b )
147
- // TODO(dsymonds): Handle multipart/form-data
149
+ case "multipart/form-data" :
150
+ r .Files = make (map [string ][]byte )
151
+ boundary := strings .Split (ct , "boundary=" , 2 )[1 ]
152
+ var b []byte
153
+ if b , err = ioutil .ReadAll (r .Body ); err != nil {
154
+ return err
155
+ }
156
+ parts := bytes .Split (b , strings .Bytes ("--" + boundary + "\r \n " ), 0 )
157
+ for _ , data := range (parts ) {
158
+ if len (data ) == 0 {
159
+ continue
160
+ }
161
+ var line []byte
162
+ var rest = data
163
+ headers := map [string ]string {}
164
+ isfile := false
165
+ var name string
166
+ for {
167
+ res := bytes .Split (rest , []byte {'\r' , '\n' }, 2 )
168
+ if len (res ) != 2 {
169
+ break
170
+ }
171
+ line = res [0 ]
172
+ rest = res [1 ]
173
+ if len (line ) == 0 {
174
+ break
175
+ }
176
+
177
+ header := strings .Split (string (line ), ":" , 2 )
178
+ n := strings .TrimSpace (header [0 ])
179
+ v := strings .TrimSpace (header [1 ])
180
+ if n == "Content-Disposition" {
181
+ parts := strings .Split (v , ";" , 0 )
182
+ for _ , parm := range (parts [1 :]) {
183
+ pp := strings .Split (parm , "=" , 2 )
184
+ pn := strings .TrimSpace (pp [0 ])
185
+ pv := strings .TrimSpace (pp [1 ])
186
+ if pn == "name" {
187
+ name = pv [1 : len (pv )- 1 ]
188
+ } else if pn == "filename" {
189
+ isfile = true
190
+ }
191
+ }
192
+ }
193
+
194
+ headers [n ] = v
195
+ }
196
+ if isfile {
197
+ parts = bytes .Split (rest , strings .Bytes ("\r \n --" + boundary + "--\r \n " ), 0 )
198
+ r .Files [name ] = parts [0 ]
199
+ }
200
+ }
148
201
default :
149
202
return & badStringError {"unknown Content-Type" , ct }
150
203
}
@@ -174,6 +227,16 @@ func (r *Request) ParseCookies() (err os.Error) {
174
227
}
175
228
176
229
func (r * Request ) HasParam (name string ) bool {
230
+ if r .Params == nil || len (r .Params ) == 0 {
231
+ return false
232
+ }
177
233
_ , ok := r .Params [name ]
178
234
return ok
179
235
}
236
+ func (r * Request ) HasFile (name string ) bool {
237
+ if r .Files == nil || len (r .Files ) == 0 {
238
+ return false
239
+ }
240
+ _ , ok := r .Files [name ]
241
+ return ok
242
+ }
0 commit comments