vweb: split and parse Content-Type header correctly (#9756)

pull/9765/head
Miccah 2021-04-16 00:46:06 -05:00 committed by GitHub
parent b11b744630
commit e2be3ec396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 5 deletions

View File

@ -147,6 +147,7 @@ fn lines_to_string(len int, lines []string, start int, end int) string {
for i in start .. end { for i in start .. end {
sb.writeln(lines[i]) sb.writeln(lines[i])
} }
sb.cut_last(1) // last newline
res := sb.str() res := sb.str()
unsafe { sb.free() } unsafe { sb.free() }
return res return res

View File

@ -112,17 +112,16 @@ ${contents[1]}
--------------------------$boundary-- --------------------------$boundary--
' '
form, files := parse_multipart_form(data, boundary) form, files := parse_multipart_form(data, boundary)
// TODO: remove newlines
assert files == map{ assert files == map{
names[0]: [FileData{ names[0]: [FileData{
filename: file filename: file
content_type: ct content_type: ct
data: contents[0] + '\n' data: contents[0]
}] }]
} }
assert form == map{ assert form == map{
names[1]: contents[1] + '\n' names[1]: contents[1]
} }
} }

View File

@ -208,6 +208,31 @@ fn test_http_client_json_post() ? {
assert '$ouser' == '$nuser2' assert '$ouser' == '$nuser2'
} }
fn test_http_client_multipart_form_data() ? {
boundary := '6844a625b1f0b299'
name := 'foo'
ct := 'multipart/form-data; boundary=------------------------$boundary'
contents := 'baz buzz'
data := '--------------------------$boundary
Content-Disposition: form-data; name=\"$name\"
$contents
--------------------------$boundary--
'
mut x := http.fetch('http://127.0.0.1:$sport/form_echo',
method: .post
header: http.new_header(
key: .content_type
value: ct
)
data: data
) ?
$if debug_net_socket_client ? {
eprintln('/form_echo endpoint response: $x')
}
assert x.text == contents
}
fn test_http_client_shutdown_does_not_work_without_a_cookie() { fn test_http_client_shutdown_does_not_work_without_a_cookie() {
x := http.get('http://127.0.0.1:$sport/shutdown') or { x := http.get('http://127.0.0.1:$sport/shutdown') or {
assert err.msg == '' assert err.msg == ''

View File

@ -85,6 +85,12 @@ pub fn (mut app App) json_echo() vweb.Result {
return app.ok(app.req.data) return app.ok(app.req.data)
} }
['/form_echo'; post]
pub fn (mut app App) form_echo() vweb.Result {
app.set_content_type(app.req.header.get(.content_type) or { '' })
return app.ok(app.form['foo'])
}
// Make sure [post] works without the path // Make sure [post] works without the path
[post] [post]
pub fn (mut app App) json() vweb.Result { pub fn (mut app App) json() vweb.Result {

View File

@ -336,8 +336,9 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
page_gen_start: page_gen_start page_gen_start: page_gen_start
} }
if req.method in vweb.methods_with_form { if req.method in vweb.methods_with_form {
if 'multipart/form-data' in req.header.values(.content_type) { ct := req.header.get(.content_type) or { '' }.split(';').map(it.trim_left(' \t'))
boundary := req.header.values(.content_type).filter(it.starts_with('boundary=')) if 'multipart/form-data' in ct {
boundary := ct.filter(it.starts_with('boundary='))
if boundary.len != 1 { if boundary.len != 1 {
send_string(mut conn, vweb.http_400) or {} send_string(mut conn, vweb.http_400) or {}
return return