From fe02feffa68b9cce558cae5cf57b3e7b5af32689 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 23 Apr 2026 18:19:34 +0300 Subject: [PATCH] net.http: fix Strange error message for invalid site on Windows (http.get) (fixes #16968) --- vlib/net/http/backend_vschannel_windows.c.v | 5 +-- vlib/net/http/response_test.v | 22 +++++++++ vlib/net/http/util.v | 50 +++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/vlib/net/http/backend_vschannel_windows.c.v b/vlib/net/http/backend_vschannel_windows.c.v index f499c9ab1..f9959e35e 100644 --- a/vlib/net/http/backend_vschannel_windows.c.v +++ b/vlib/net/http/backend_vschannel_windows.c.v @@ -32,8 +32,7 @@ fn vschannel_ssl_do(req &Request, port int, method Method, host_name string, pat C.vschannel_cleanup(&ctx) if length <= 0 { if err_code != 0 { - return error_with_code('http: vschannel request failed: ${vschannel_error_message(err_code)}', - err_code) + return vschannel_request_error(err_code) } return error('http: vschannel request failed') } @@ -47,5 +46,5 @@ fn vschannel_ssl_do(req &Request, port int, method Method, host_name string, pat if req.on_finish != unsafe { nil } { req.on_finish(req, u64(response_text.len))! } - return parse_response(response_text) + return vschannel_parse_response(response_text, err_code) } diff --git a/vlib/net/http/response_test.v b/vlib/net/http/response_test.v index 09c7cb086..1e0e5af7e 100644 --- a/vlib/net/http/response_test.v +++ b/vlib/net/http/response_test.v @@ -123,3 +123,25 @@ fn test_vschannel_error_message_formats_windows_wsa_errors() { assert vschannel_error_message(11001) == '(11001) wsahost_not_found' } } + +fn test_vschannel_request_error_normalizes_connect_failures() { + err := vschannel_request_error(vschannel_sec_e_internal_error) + assert err.msg() == vschannel_connect_failed_msg + assert err.code() == vschannel_sec_e_internal_error +} + +fn test_vschannel_request_error_keeps_other_codes() { + err := vschannel_request_error(42) + assert err.msg() == 'http: vschannel request failed: 42' + assert err.code() == 42 +} + +fn test_vschannel_parse_response_normalizes_connect_failure_output() { + vschannel_parse_response('Error 10057 sending data to server (1)\nError performing handshake', + 0) or { + assert err.msg() == vschannel_connect_failed_msg + assert err.code() == 0 + return + } + assert false +} diff --git a/vlib/net/http/util.v b/vlib/net/http/util.v index 32476fe20..935a37fb0 100644 --- a/vlib/net/http/util.v +++ b/vlib/net/http/util.v @@ -5,6 +5,10 @@ module http import net +const vschannel_connect_failed_msg = 'Failed to connect to host' + +const vschannel_sec_e_internal_error = -2146893052 + // A fast version that avoids allocations in s.split() // returns the locations of the 2 spaces // "GET / HTTP/1.1" => ["GET" "/" "HTTP/1.1"] @@ -26,3 +30,49 @@ fn vschannel_error_message(err_code int) string { } return '${err_code}' } + +fn vschannel_connect_error(err_code int) IError { + if err_code == 0 { + return error(vschannel_connect_failed_msg) + } + return error_with_code(vschannel_connect_failed_msg, err_code) +} + +fn vschannel_should_report_connect_failure(err_code int) bool { + if err_code == vschannel_sec_e_internal_error { + return true + } + $if windows { + return err_code in [int(net.WsaError.wsaenotconn), int(net.WsaError.wsaenetdown), + int(net.WsaError.wsaenetunreach), int(net.WsaError.wsaetimedout), + int(net.WsaError.wsaeconnrefused), int(net.WsaError.wsaehostdown), + int(net.WsaError.wsaehostunreach), int(net.WsaError.wsahost_not_found), + int(net.WsaError.wsatry_again), int(net.WsaError.wsano_recovery), + int(net.WsaError.wsano_data)] + } + return false +} + +fn vschannel_looks_like_connect_failure_response(response_text string) bool { + trimmed := response_text.trim_space() + return trimmed.starts_with('Error ') && (trimmed.contains('sending data to server') + || trimmed.contains('Error performing handshake')) +} + +fn vschannel_request_error(err_code int) IError { + if vschannel_should_report_connect_failure(err_code) { + return vschannel_connect_error(err_code) + } + return error_with_code('http: vschannel request failed: ${vschannel_error_message(err_code)}', + err_code) +} + +fn vschannel_parse_response(response_text string, err_code int) !Response { + if response_text.len < 5 || response_text[..5].to_lower() != 'http/' { + if vschannel_should_report_connect_failure(err_code) + || vschannel_looks_like_connect_failure_response(response_text) { + return vschannel_connect_error(err_code) + } + } + return parse_response(response_text) +} -- 2.39.5