From f59323023d4e8a9487098049c4828021534a7ff4 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 05:09:24 +0300 Subject: [PATCH] net.ssl: fix mbedtls http.get_text returning nothing (fixes #23717) --- .../mbedtls_concurrent_large_response_test.v | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/vlib/net/mbedtls/mbedtls_concurrent_large_response_test.v b/vlib/net/mbedtls/mbedtls_concurrent_large_response_test.v index 42edbb951..456b3fc9a 100644 --- a/vlib/net/mbedtls/mbedtls_concurrent_large_response_test.v +++ b/vlib/net/mbedtls/mbedtls_concurrent_large_response_test.v @@ -94,6 +94,26 @@ fn test_https_request_timeout_closes_the_connection() { panic('expected the HTTPS request to time out') } +fn test_https_chunked_body_is_returned_by_http_get_text() { + mut port_listener := net.listen_tcp(.ip, '127.0.0.1:0')! + port := port_listener.addr()!.port()! + port_listener.close()! + + mut listener := mbedtls.new_ssl_listener('127.0.0.1:${port}', mbedtls.SSLConnectConfig{ + cert: concurrent_large_response_test_cert + cert_key: concurrent_large_response_test_key + validate: false + in_memory_verification: true + })! + expected_body := concurrent_large_response_body() + server := spawn serve_chunked_html_response(mut listener, expected_body) + + body := http.get_text('https://127.0.0.1:${port}/chunked') + server.wait() + + assert body == expected_body +} + fn concurrent_large_response_body() string { return '' + '
payload
'.repeat(concurrent_large_response_links) + @@ -129,6 +149,14 @@ fn serve_large_html_responses(mut listener mbedtls.SSLListener, body string, req handlers.wait() } +fn serve_chunked_html_response(mut listener mbedtls.SSLListener, body string) { + defer { + listener.shutdown() or {} + } + mut conn := listener.accept() or { panic(err) } + write_chunked_html_response(mut conn, body) +} + fn write_large_html_response(mut conn mbedtls.SSLConn, body string) { defer { conn.shutdown() or {} @@ -150,6 +178,31 @@ fn write_large_html_response(mut conn mbedtls.SSLConn, body string) { } } +fn write_chunked_html_response(mut conn mbedtls.SSLConn, body string) { + defer { + conn.shutdown() or {} + } + mut request_buf := []u8{len: 2048} + _ = conn.read(mut request_buf) or { return } + header := 'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: close\r\n\r\n' + conn.write_string(header) or { return } + mut start := 0 + for start < body.len { + end := if start + concurrent_large_response_chunk_size > body.len { + body.len + } else { + start + concurrent_large_response_chunk_size + } + chunk := body[start..end] + conn.write_string('${chunk.len:x}\r\n') or { return } + conn.write_string(chunk) or { return } + conn.write_string('\r\n') or { return } + start = end + time.sleep(1 * time.millisecond) + } + conn.write_string('0\r\n\r\n') or { return } +} + fn concurrent_large_response_worker(mut pp pool.PoolProcessor, idx int, _wid int) &ConcurrentLargeResponseResult { url := pp.get_item[string](idx) ctx := unsafe { &ConcurrentLargeResponseContext(pp.get_shared_context()) } -- 2.39.5