diff --git a/vlib/strings/builder_c.v b/vlib/strings/builder_c.v index a9570144c9..5051cc2f08 100644 --- a/vlib/strings/builder_c.v +++ b/vlib/strings/builder_c.v @@ -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++ diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 4ad2c20aeb..c9b7deb747 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -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(app mut T, port int) { conn := l.accept() or { panic('accept() failed') } //foobar() // TODO move this to handle_conn(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(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(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(app mut T, port int) { } } - -pub fn foobar() { -} - 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') +}