1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

vweb: fix parsing of form fields, send with multipart/form-data (by JS fetch)

This commit is contained in:
Delyan Angelov
2023-07-14 16:07:52 +03:00
parent f1bc5e6d46
commit 9047f7c9a8
5 changed files with 72 additions and 24 deletions

View File

@@ -304,14 +304,19 @@ pub fn (err MultiplePathAttributesError) msg() string {
// HTTP request body. It is the inverse of parse_multipart_form. Returns
// (body, boundary).
// Note: Form keys should not contain quotes
[manualfree]
fn multipart_form_body(form map[string]string, files map[string][]FileData) (string, string) {
alpha_numeric := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
boundary := rand.string_from_set(alpha_numeric, 64)
rboundary := rand.ulid()
defer {
unsafe { rboundary.free() }
}
mut sb := strings.new_builder(1024)
defer {
unsafe { sb.free() }
}
for name, value in form {
sb.write_string('\r\n--')
sb.write_string(boundary)
sb.write_string(rboundary)
sb.write_string('\r\nContent-Disposition: form-data; name="')
sb.write_string(name)
sb.write_string('"\r\n\r\n')
@@ -320,7 +325,7 @@ fn multipart_form_body(form map[string]string, files map[string][]FileData) (str
for name, fs in files {
for f in fs {
sb.write_string('\r\n--')
sb.write_string(boundary)
sb.write_string(rboundary)
sb.write_string('\r\nContent-Disposition: form-data; name="')
sb.write_string(name)
sb.write_string('"; filename="')
@@ -332,9 +337,9 @@ fn multipart_form_body(form map[string]string, files map[string][]FileData) (str
}
}
sb.write_string('\r\n--')
sb.write_string(boundary)
sb.write_string(rboundary)
sb.write_string('--')
return sb.str(), boundary
return sb.str(), rboundary
}
struct LineSegmentIndexes {

View File

@@ -154,6 +154,28 @@ ${contents[1]}\r
}
}
fn test_parse_multipart_form2() {
boundary := '---------------------------27472781931927549291906391339'
data := '--${boundary}\r
Content-Disposition: form-data; name="username"\r
\r
admin\r
--${boundary}\r
Content-Disposition: form-data; name="password"\r
\r
admin123\r
--${boundary}--\r
'
form, files := parse_multipart_form(data, boundary)
for k, v in form {
eprintln('> k: ${k} | v: ${v}')
eprintln('>> k.bytes(): ${k.bytes()}')
eprintln('>> v.bytes(): ${v.bytes()}')
}
assert form['username'] == 'admin'
assert form['password'] == 'admin123'
}
fn test_multipart_form_body() {
files := {
'foo': [
@@ -175,7 +197,7 @@ fn test_multipart_form_body() {
}
fn test_parse_large_body() {
body := 'A'.repeat(101) // greater than max_bytes
body := 'A'.repeat(10_001) // greater than max_bytes
req := 'GET / HTTP/1.1\r\nContent-Length: ${body.len}\r\n\r\n${body}'
mut reader_ := reader(req)
result := parse_request(mut reader_)!