diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 8ea7326319..fba1917ce9 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -1216,13 +1216,22 @@ pub fn (s string) all_before_last(dot string) string { } pub fn (s string) all_after(dot string) string { + pos := s.index(dot) or { + return s + } + return s.right(pos + dot.len) +} + +pub fn (s string) all_after_last(dot string) string { pos := s.last_index(dot) or { return s } return s.right(pos + dot.len) } -pub fn (s string) after(dot string) string { return s.all_after(dot) } +pub fn (s string) after(dot string) string { + return s.all_after_last(dot) +} pub fn (s string) after_char(dot byte) string { mut pos := 0 diff --git a/vlib/net/http/backend_nix.c.v b/vlib/net/http/backend_nix.c.v index ff4f120040..a7d699031d 100644 --- a/vlib/net/http/backend_nix.c.v +++ b/vlib/net/http/backend_nix.c.v @@ -20,72 +20,54 @@ import strings #flag darwin -L/usr/local/opt/openssl/lib #include -struct C.ssl_st +struct C.ssl_st {} fn C.SSL_library_init() - fn C.TLSv1_2_method() voidptr - fn C.SSL_CTX_set_options() - fn C.SSL_CTX_new() voidptr - fn C.SSL_CTX_set_verify_depth() - fn C.SSL_CTX_load_verify_locations() int - fn C.BIO_new_ssl_connect() voidptr - fn C.BIO_set_conn_hostname() int - fn C.BIO_get_ssl() - fn C.SSL_set_cipher_list() int - fn C.BIO_do_connect() int - fn C.BIO_do_handshake() int - fn C.SSL_get_peer_certificate() int - fn C.SSL_get_verify_result() int - fn C.SSL_set_tlsext_host_name() int - fn C.BIO_puts() - fn C.BIO_read() int - fn C.BIO_free_all() - fn C.SSL_CTX_free() - fn init() int { C.SSL_library_init() return 1 } const ( -buf_size = 500 // 1536 + buf_size = 500 // 1536 + debug_line_separator = '--------------------------------' ) fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { @@ -117,41 +99,36 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { // ///// req_headers := req.build_request_headers(method, host_name, path) C.BIO_puts(web, req_headers.str) - mut headers := strings.new_builder(100) - mut h := '' + mut headers := '' mut headers_done := false - mut sb := strings.new_builder(100) + mut body_builder := strings.new_builder(100) mut buff := [buf_size]byte - mut is_chunk_encoding := false + mut readcounter := 0 for { + readcounter++ len := C.BIO_read(web, buff, buf_size) if len <= 0 { break } mut chunk := (tos(buff, len)) - if !headers_done && chunk.contains('\r\n\r\n') { - headers_done = true - headers.write(chunk.all_before('\r\n\r\n')) - h = headers.str() - //println(h) - sb.write(chunk.after('\r\n\r\n')) - // TODO for some reason this can be missing from headers - is_chunk_encoding = false //h.contains('chunked') - //println(sb.str()) - continue + $if debug_http ? { + eprintln('ssl_do, read ${readcounter:4d} | headers_done: $headers_done') + eprintln(debug_line_separator) + eprintln(chunk) + eprintln(debug_line_separator) } - // TODO clean this up - if is_chunk_encoding && len > 6 && ((buff[3] == 13 && buff[4] == 10) || (buff[2] ==13 && buff[3]==10) - || (buff[4] == 13 && buff[5] == 10) ) { - chunk = chunk.after_char(10) - } - if chunk.len > 3 && chunk[chunk.len-2] == 13 && chunk[chunk.len-1] == 10 { - chunk = chunk[..chunk.len-2] + if !headers_done { + headers += chunk + if headers.contains('\r\n\r\n') { + headers_done = true + body_start := headers.all_after('\r\n\r\n') + body_builder.write(body_start) + headers = headers.all_before('\r\n\r\n') + continue + } } if headers_done { - sb.write(chunk) - } else { - headers.write(chunk) + body_builder.write(chunk) } } if !isnil(web) { @@ -160,8 +137,16 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { if !isnil(ctx) { C.SSL_CTX_free(ctx) } - body:= sb.str() - //println(body) - return parse_response(h +'\r\n\r\n'+ body) + body := body_builder.str() + $if debug_http ? { + eprintln('> http headers:') + eprintln(debug_line_separator) + eprintln(headers) + eprintln(debug_line_separator) + eprintln('> http body:') + eprintln(debug_line_separator) + eprintln(body) + eprintln(debug_line_separator) + } + return parse_response(headers + '\r\n\r\n' + body) } - diff --git a/vlib/os/os.v b/vlib/os/os.v index 250320666e..62030a05ef 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -675,7 +675,7 @@ pub fn base_dir(path string) string { } pub fn file_name(path string) string { - return path.all_after(path_separator) + return path.all_after_last(path_separator) } // input returns a one-line string from stdin, after printing a prompt diff --git a/vlib/stbi/stbi.v b/vlib/stbi/stbi.v index c1fe0298b8..898cc58cc1 100644 --- a/vlib/stbi/stbi.v +++ b/vlib/stbi/stbi.v @@ -27,7 +27,7 @@ fn C.stbi_image_free() fn C.stbi_set_flip_vertically_on_load() pub fn load(path string) Image { - ext := path.all_after('.') + ext := path.all_after_last('.') mut res := Image { ok: true ext: ext diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 003e4c561d..fcf8ed4447 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -785,7 +785,7 @@ pub fn (mut p Parser) name_expr() ast.Expr { } } if p.peek_tok.kind == .dot && !known_var && (language != .v || p.known_import(p.tok.lit) || - p.mod.all_after('.') == p.tok.lit) { + p.mod.all_after_last('.') == p.tok.lit) { if language == .c { mod = 'C' } else if language == .js { diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index cbbebe9b23..f75dcba5f6 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1009,7 +1009,7 @@ fn (mut s Scanner) debug_tokens() { s.pos = 0 s.is_started = false s.is_debug = true - fname := s.file_path.all_after(os.path_separator) + fname := s.file_path.all_after_last(os.path_separator) println('\n===DEBUG TOKENS $fname===') for { tok := s.scan() diff --git a/vlib/vweb/tmpl/tmpl.v b/vlib/vweb/tmpl/tmpl.v index 3a8693e04e..e248415f4b 100644 --- a/vlib/vweb/tmpl/tmpl.v +++ b/vlib/vweb/tmpl/tmpl.v @@ -26,7 +26,7 @@ pub fn compile_template(path string) string { } lines := html.split_into_lines() mut s := strings.new_builder(1000) - // base := path.all_after('/').replace('.html', '') + // base := path.all_after_last('/').replace('.html', '') s.writeln(" mut sb := strings.new_builder(${lines.len * 30}) header := \' \' // TODO remove