Skip to content

Commit 76fd55a

Browse files
authored
vweb: fix multipart_form parsing (#17953)
1 parent 8b2887d commit 76fd55a

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
lines changed

vlib/vweb/parse.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ fn parse_form_from_request(request http.Request) !(map[string]string, map[string
7171
if boundary.len != 1 {
7272
return error('detected more that one form-data boundary')
7373
}
74-
form, files = http.parse_multipart_form(request.data, boundary[0][9..])
74+
// omit 'boundary="' and the last '"'
75+
boundary_str := boundary[0].substr(10, boundary[0].len - 1)
76+
form, files = http.parse_multipart_form(request.data, boundary_str)
7577
} else {
7678
form = http.parse_form(request.data)
7779
}

vlib/vweb/tests/vweb_test.v

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -205,29 +205,37 @@ fn test_http_client_json_post() {
205205
}
206206

207207
fn test_http_client_multipart_form_data() {
208-
boundary := '6844a625b1f0b299'
209-
name := 'foo'
210-
ct := 'multipart/form-data; boundary=${boundary}'
211-
contents := 'baz buzz'
212-
data := '--${boundary}\r
213-
Content-Disposition: form-data; name="${name}"\r
214-
\r
215-
${contents}\r
216-
--${boundary}--\r
217-
'
218-
mut x := http.fetch(
219-
url: 'http://${localserver}/form_echo'
220-
method: .post
221-
header: http.new_header(
222-
key: .content_type
223-
value: ct
224-
)
225-
data: data
226-
)!
208+
mut form_config := http.PostMultipartFormConfig{
209+
form: {
210+
'foo': 'baz buzz'
211+
}
212+
}
213+
214+
mut x := http.post_multipart_form('http://${localserver}/form_echo', form_config)!
215+
216+
$if debug_net_socket_client ? {
217+
eprintln('/form_echo endpoint response: ${x}')
218+
}
219+
assert x.body == form_config.form['foo']
220+
221+
mut files := []http.FileData{}
222+
files << http.FileData{
223+
filename: 'vweb'
224+
content_type: 'text'
225+
data: '"vweb test"'
226+
}
227+
228+
mut form_config_files := http.PostMultipartFormConfig{
229+
files: {
230+
'file': files
231+
}
232+
}
233+
234+
x = http.post_multipart_form('http://${localserver}/file_echo', form_config_files)!
227235
$if debug_net_socket_client ? {
228236
eprintln('/form_echo endpoint response: ${x}')
229237
}
230-
assert x.body == contents
238+
assert x.body == files[0].data
231239
}
232240

233241
fn test_http_client_shutdown_does_not_work_without_a_cookie() {

vlib/vweb/tests/vweb_test_server.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ pub fn (mut app App) form_echo() vweb.Result {
9595
return app.ok(app.form['foo'])
9696
}
9797

98+
['/file_echo'; post]
99+
pub fn (mut app App) file_echo() vweb.Result {
100+
if 'file' !in app.files {
101+
app.set_status(500, '')
102+
return app.text('no file')
103+
}
104+
105+
return app.text(app.files['file'][0].data)
106+
}
107+
98108
// Make sure [post] works without the path
99109
[post]
100110
pub fn (mut app App) json() vweb.Result {

0 commit comments

Comments
 (0)