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) {
b.buf << data
b.len++

View File

@ -32,6 +32,7 @@ const (
'.svg': 'image/svg+xml',
'.xml': 'text/xml; charset=utf-8'
}
MAX_HTTP_POST_SIZE = 1024 * 1024
)
pub struct Context {
@ -125,12 +126,25 @@ pub fn run<T>(app mut T, port int) {
conn := l.accept() or { panic('accept() failed') }
//foobar<T>()
// TODO move this to handle_conn<T>(conn, app)
first_line:= conn.read_line()
if first_line == '' {
message := readall(conn)
if message.len > MAX_HTTP_POST_SIZE {
println('message.len = $message.len > MAX_HTTP_POST_SIZE')
conn.send_string(HTTP_500) or {}
conn.close() or {}
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
// "GET / HTTP/1.1"
//first_line := s.all_before('\n')
@ -142,13 +156,18 @@ pub fn run<T>(app mut T, port int) {
continue
}
mut headers := []string
for {
if headers.len >= 30 { break }
header := conn.read_line()
headers << header
//println('header="$header" len = ' + header.len.str())
if header.len <= 2 { break }
mut body := ''
mut in_headers := true
for line in lines[1..] {
sline := strip(line)
if sline == '' { in_headers = false }
if in_headers {
headers << sline
} else {
body += strip(sline) + '\r\n'
}
}
mut action := vals[1][1..].all_before('/')
if action.contains('?') {
action = action.all_before('?')
@ -178,19 +197,8 @@ pub fn run<T>(app mut T, port int) {
}
//}
if req.method in methods_with_form {
/*
for {
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)
body = strip(body)
app.vweb.parse_form(body)
}
if vals.len < 2 {
$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) {
if !(ctx.req.method in methods_with_form) {
return
@ -248,6 +252,8 @@ fn (ctx mut Context) parse_form(s string) {
ctx.form[key] = val
}
//}
// todo: parse form-data and application/json
// ...
}
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_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')
}