vweb: fix empty post request blocking

pull/3060/head
taojy123 2019-12-12 00:20:46 +08:00 committed by Alexander Medvednikov
parent 7dcd47369b
commit 28f76f10db
2 changed files with 56 additions and 25 deletions

View File

@ -19,6 +19,11 @@ pub fn new_builder(initial_size int) Builder {
} }
} }
pub fn (b mut Builder) write_bytes(bytes byteptr, howmany int) {
b.buf.push_many(bytes, howmany)
b.len += howmany
}
pub fn (b mut Builder) write_b(data byte) { pub fn (b mut Builder) write_b(data byte) {
b.buf << data b.buf << data
b.len++ b.len++

View File

@ -32,6 +32,7 @@ const (
'.svg': 'image/svg+xml', '.svg': 'image/svg+xml',
'.xml': 'text/xml; charset=utf-8' '.xml': 'text/xml; charset=utf-8'
} }
MAX_HTTP_POST_SIZE = 1024 * 1024
) )
pub struct Context { pub struct Context {
@ -125,12 +126,25 @@ pub fn run<T>(app mut T, port int) {
conn := l.accept() or { panic('accept() failed') } conn := l.accept() or { panic('accept() failed') }
//foobar<T>() //foobar<T>()
// TODO move this to handle_conn<T>(conn, app) // TODO move this to handle_conn<T>(conn, app)
first_line:= conn.read_line() message := readall(conn)
if first_line == '' {
if message.len > MAX_HTTP_POST_SIZE {
println('message.len = $message.len > MAX_HTTP_POST_SIZE')
conn.send_string(HTTP_500) or {} conn.send_string(HTTP_500) or {}
conn.close() or {} conn.close() or {}
continue continue
} }
lines := message.split_into_lines()
if lines.len < 2 {
conn.send_string(HTTP_500) or {}
conn.close() or {}
continue
}
first_line := strip(lines[0])
$if debug { println(first_line) }
// Parse the first line // Parse the first line
// "GET / HTTP/1.1" // "GET / HTTP/1.1"
//first_line := s.all_before('\n') //first_line := s.all_before('\n')
@ -142,13 +156,18 @@ pub fn run<T>(app mut T, port int) {
continue continue
} }
mut headers := []string mut headers := []string
for { mut body := ''
if headers.len >= 30 { break } mut in_headers := true
header := conn.read_line() for line in lines[1..] {
headers << header sline := strip(line)
//println('header="$header" len = ' + header.len.str()) if sline == '' { in_headers = false }
if header.len <= 2 { break } if in_headers {
headers << sline
} else {
body += strip(sline) + '\r\n'
} }
}
mut action := vals[1][1..].all_before('/') mut action := vals[1][1..].all_before('/')
if action.contains('?') { if action.contains('?') {
action = action.all_before('?') action = action.all_before('?')
@ -178,19 +197,8 @@ pub fn run<T>(app mut T, port int) {
} }
//} //}
if req.method in methods_with_form { if req.method in methods_with_form {
/* body = strip(body)
for { app.vweb.parse_form(body)
line := conn.read_line()
if line == '' || line == '\r\n' {
break
}
//if line.contains('POST') || line == '' {
//break
//}
}
*/
line := conn.read_line()
app.vweb.parse_form(line)
} }
if vals.len < 2 { if vals.len < 2 {
$if debug { $if debug {
@ -219,10 +227,6 @@ pub fn run<T>(app mut T, port int) {
} }
} }
pub fn foobar<T>() {
}
fn (ctx mut Context) parse_form(s string) { fn (ctx mut Context) parse_form(s string) {
if !(ctx.req.method in methods_with_form) { if !(ctx.req.method in methods_with_form) {
return return
@ -248,6 +252,8 @@ fn (ctx mut Context) parse_form(s string) {
ctx.form[key] = val ctx.form[key] = val
} }
//} //}
// todo: parse form-data and application/json
// ...
} }
fn (ctx mut Context) scan_static_directory(directory_path, mount_path string) { fn (ctx mut Context) scan_static_directory(directory_path, mount_path string) {
@ -297,3 +303,23 @@ pub fn (ctx mut Context) serve_static(url, file_path, mime_type string) {
ctx.static_files[url] = file_path ctx.static_files[url] = file_path
ctx.static_mime_types[url] = mime_type ctx.static_mime_types[url] = mime_type
} }
fn readall(conn net.Socket) string {
// read all message from socket
mut message := ''
buf := [1024]byte
for {
n := C.recv(conn.sockfd, buf, 1024, 2)
m := conn.crecv(buf, 1024)
message += string( byteptr(buf), m )
if message.len > MAX_HTTP_POST_SIZE { break }
if n == m { break }
}
return message
}
fn strip(s string) string {
// strip('\nabc\r\n') => 'abc'
return s.trim('\r\n')
}