From f89cffad537ddbdf2acc3dd80a01b4426bb51a77 Mon Sep 17 00:00:00 2001 From: Vithorio Polten Date: Sat, 23 Nov 2024 13:51:28 -0300 Subject: [PATCH] net.http: send Host headers with port (when the port is != 80 or 443) (fix #22941) (#22942) --- vlib/net/http/backend.c.v | 2 +- vlib/net/http/backend_vschannel_windows.c.v | 2 +- vlib/net/http/http_proxy.v | 6 ++--- vlib/net/http/request.v | 12 ++++++--- vlib/net/http/server_test.v | 28 +++++++++++++++++++++ 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/vlib/net/http/backend.c.v b/vlib/net/http/backend.c.v index 2399f4c621..bed93d2479 100644 --- a/vlib/net/http/backend.c.v +++ b/vlib/net/http/backend.c.v @@ -33,7 +33,7 @@ fn net_ssl_do(req &Request, port int, method Method, host_name string, path stri break } - req_headers := req.build_request_headers(method, host_name, path) + req_headers := req.build_request_headers(method, host_name, port, path) $if trace_http_request ? { eprint('> ') eprint(req_headers) diff --git a/vlib/net/http/backend_vschannel_windows.c.v b/vlib/net/http/backend_vschannel_windows.c.v index f37f34d6d7..0f413ec793 100644 --- a/vlib/net/http/backend_vschannel_windows.c.v +++ b/vlib/net/http/backend_vschannel_windows.c.v @@ -20,7 +20,7 @@ fn vschannel_ssl_do(req &Request, port int, method Method, host_name string, pat C.vschannel_init(&ctx) mut buff := unsafe { malloc_noscan(C.vsc_init_resp_buff_size) } addr := host_name - sdata := req.build_request_headers(method, host_name, path) + sdata := req.build_request_headers(method, host_name, port, path) $if trace_http_request ? { eprintln('> ${sdata}') } diff --git a/vlib/net/http/http_proxy.v b/vlib/net/http/http_proxy.v index f57d4545c5..f175d64414 100644 --- a/vlib/net/http/http_proxy.v +++ b/vlib/net/http/http_proxy.v @@ -85,9 +85,9 @@ fn (pr &HttpProxy) build_proxy_headers(host string) string { } fn (pr &HttpProxy) http_do(host urllib.URL, method Method, path string, req &Request) !Response { - host_name, _ := net.split_address(host.hostname())! + host_name, port := net.split_address(host.hostname())! - s := req.build_request_headers(req.method, host_name, path) + s := req.build_request_headers(req.method, host_name, port, path) if host.scheme == 'https' { mut client := pr.ssl_dial('${host.host}:443')! @@ -99,7 +99,7 @@ fn (pr &HttpProxy) http_do(host urllib.URL, method Method, path string, req &Req // return response_text } $else { response_text := req.do_request(req.build_request_headers(req.method, host_name, - path), mut client)! + port, path), mut client)! client.shutdown()! return response_text } diff --git a/vlib/net/http/request.v b/vlib/net/http/request.v index bc67ddfca6..e734d2edb1 100644 --- a/vlib/net/http/request.v +++ b/vlib/net/http/request.v @@ -181,7 +181,7 @@ fn (req &Request) method_and_url_to_response(method Method, url urllib.URL) !Res return error('http.request.method_and_url_to_response: unsupported scheme: "${scheme}"') } -fn (req &Request) build_request_headers(method Method, host_name string, path string) string { +fn (req &Request) build_request_headers(method Method, host_name string, port int, path string) string { mut sb := strings.new_builder(4096) version := if req.version == .unknown { Version.v1_1 } else { req.version } sb.write_string(method.str()) @@ -192,7 +192,11 @@ fn (req &Request) build_request_headers(method Method, host_name string, path st sb.write_string('\r\n') if !req.header.contains(.host) { sb.write_string('Host: ') - sb.write_string(host_name) + if port != 80 && port != 443 && port != 0 { + sb.write_string('${host_name}:${port}') + } else { + sb.write_string(host_name) + } sb.write_string('\r\n') } if !req.header.contains(.user_agent) { @@ -254,8 +258,8 @@ fn (req &Request) build_request_cookies_header() string { } fn (req &Request) http_do(host string, method Method, path string) !Response { - host_name, _ := net.split_address(host)! - s := req.build_request_headers(method, host_name, path) + host_name, port := net.split_address(host)! + s := req.build_request_headers(method, host_name, port, path) mut client := net.dial_tcp(host)! client.set_read_timeout(req.read_timeout) client.set_write_timeout(req.write_timeout) diff --git a/vlib/net/http/server_test.v b/vlib/net/http/server_test.v index 552d72af22..2e9d17c835 100644 --- a/vlib/net/http/server_test.v +++ b/vlib/net/http/server_test.v @@ -248,3 +248,31 @@ fn test_my_counting_handler_on_random_port() { } assert true } + +// + +struct MyCustomHttpHostHandler {} + +fn (mut handler MyCustomHttpHostHandler) handle(req http.Request) http.Response { + dump(req.header) + return http.Response{ + body: 'Host was: ${req.header.get(.host) or { '-' }}' + } +} + +fn test_host_header_sent_to_server() { + port := 54671 + log.warn('${@FN} started') + defer { log.warn('${@FN} finished') } + mut server := &http.Server{ + handler: MyCustomHttpHostHandler{} + addr: ':${port}' + } + t := spawn server.listen_and_serve() + server.wait_till_running()! + defer { server.stop() } + dump(server.addr) + x := http.get('http://${server.addr}/')! + dump(x) + assert x.body.ends_with(':${port}') +}