From 39ee5fb9e80298cdd41330658b492736f52a98b4 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 18 May 2026 17:07:46 +0300 Subject: [PATCH] veb: add missing ssl files with RunParams definition (fixes FreeBSD CI) The ssl_notd_use_openssl.v and ssl_d_use_openssl.v files were not included when fasthttp became the default veb backend. These files define RunParams and the SSL connection handling code, which are needed by veb.v and veb_fasthttp.v. --- vlib/veb/ssl_d_use_openssl.v | 34 ++++++++ vlib/veb/ssl_notd_use_openssl.v | 134 ++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 vlib/veb/ssl_d_use_openssl.v create mode 100644 vlib/veb/ssl_notd_use_openssl.v diff --git a/vlib/veb/ssl_d_use_openssl.v b/vlib/veb/ssl_d_use_openssl.v new file mode 100644 index 000000000..e210d867a --- /dev/null +++ b/vlib/veb/ssl_d_use_openssl.v @@ -0,0 +1,34 @@ +module veb + +import net +import time + +@[params] +pub struct SSLConnectConfig { +pub: + verify string + cert string + cert_key string + validate bool + in_memory_verification bool + read_timeout time.Duration +} + +@[params] +pub struct RunParams { +pub: + // use `family: .ip, host: 'localhost'` when you want it to bind only to 127.0.0.1 + family net.AddrFamily = .ip6 + host string + port int = default_port + nr_workers int = 1 + show_startup_message bool = true + timeout_in_seconds int = 30 + max_request_buffer_size int = 8192 + benchmark_page_generation bool // for the "page rendered in X ms" + ssl_config SSLConnectConfig +} + +fn run_at_with_ssl[A, X](mut _global_app A, _params RunParams) ! { + return error('veb HTTPS server requires net.mbedtls; -d use_openssl only avoids mbedtls for HTTP apps') +} diff --git a/vlib/veb/ssl_notd_use_openssl.v b/vlib/veb/ssl_notd_use_openssl.v new file mode 100644 index 000000000..e5324832d --- /dev/null +++ b/vlib/veb/ssl_notd_use_openssl.v @@ -0,0 +1,134 @@ +module veb + +import io +import net +import net.http +import net.mbedtls +import os +import time + +@[params] +pub struct RunParams { +pub: + // use `family: .ip, host: 'localhost'` when you want it to bind only to 127.0.0.1 + family net.AddrFamily = .ip6 + host string + port int = default_port + nr_workers int = 1 + show_startup_message bool = true + timeout_in_seconds int = 30 + max_request_buffer_size int = 8192 + benchmark_page_generation bool // for the "page rendered in X ms" + ssl_config mbedtls.SSLConnectConfig +} + +fn run_at_with_ssl[A, X](mut global_app A, params RunParams) ! { + routes := generate_routes[A, X](global_app)! + controllers_sorted := check_duplicate_routes_in_controllers[A](global_app, routes)! + if params.show_startup_message { + println('[veb] Running app on https://${startup_host(params)}:${params.port}/') + } + flush_stdout() + mut ssl_listener := mbedtls.new_ssl_listener(listen_addr(params), params.ssl_config)! + defer { + ssl_listener.shutdown() or {} + } + ssl_params := &SslRequestParams{ + global_app: unsafe { voidptr(&global_app) } + controllers_sorted: controllers_sorted + routes: &routes + benchmark_page_generation: params.benchmark_page_generation + max_request_buffer_size: if params.max_request_buffer_size > 0 { + params.max_request_buffer_size + } else { + max_read + } + } + $if A is BeforeAcceptApp { + global_app.before_accept_loop() + } + for { + mut ssl_conn := ssl_listener.accept() or { + eprintln('[veb] accept() failed, reason: ${err}; skipping') + continue + } + ssl_conn.duration = params.timeout_in_seconds * time.second + spawn handle_ssl_connection[A, X](mut ssl_conn, ssl_params) + } +} + +fn handle_ssl_connection[A, X](mut ssl_conn mbedtls.SSLConn, params &SslRequestParams) { + defer { + ssl_conn.shutdown() or {} + } + mut reader := io.new_buffered_reader( + reader: ssl_conn + cap: params.max_request_buffer_size + ) + defer { + unsafe { + reader.free() + } + } + for { + req := read_request_from_buffered_reader(mut reader) or { + if err !is io.Eof { + write_ssl_response(mut ssl_conn, http_400) or {} + } + return + } + completed_context := handle_ssl_request[A, X](req, params) or { + write_ssl_response(mut ssl_conn, http_400) or {} + return + } + if completed_context.takeover_mode != .none { + eprintln('[veb] HTTPS connections do not support takeover connections yet; closing the connection after this response.') + } + write_ssl_context_response(mut ssl_conn, completed_context) or { + eprintln('[veb] error sending HTTPS response: ${err}') + return + } + if completed_context.takeover_mode != .none + || should_close_connection(completed_context.req, completed_context.res, completed_context.client_wants_to_close) { + return + } + } +} + +fn write_ssl_context_response(mut ssl_conn mbedtls.SSLConn, completed_context &Context) ! { + if !completed_context.done && completed_context.return_type == .normal { + return error('context did not send a response') + } + match completed_context.return_type { + .normal { + write_ssl_response(mut ssl_conn, completed_context.res)! + } + .file { + write_ssl_response(mut ssl_conn, completed_context.res)! + if completed_context.return_file == '' { + return error('missing file response path') + } + mut file := os.open(completed_context.return_file)! + defer { + file.close() + } + mut buf := []u8{len: max_read} + for { + n := file.read(mut buf) or { + if err is io.Eof { + break + } + return err + } + if n <= 0 { + break + } + ssl_conn.write(buf[..n])! + } + } + } +} + +fn write_ssl_response(mut ssl_conn mbedtls.SSLConn, resp http.Response) ! { + ssl_conn.write(resp.bytes())! +} -- 2.39.5