From d0a07e555577dcd4a8f55f1b45d9e8e4e6366ab7 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 10 Mar 2026 17:27:26 +0100 Subject: HttpClient using libcurl, Unix Sockets for HTTP. HTTPS support (#770) The main goal of this change is to eliminate the cpr back-end altogether and replace it with the curl implementation. I would expect to drop cpr as soon as we feel happy with the libcurl back-end. That would leave us with a direct dependency on libcurl only, and cpr can be eliminated as a dependency. ### HttpClient Backend Overhaul - Implemented a new **libcurl-based HttpClient** backend (`httpclientcurl.cpp`, ~2000 lines) as an alternative to the cpr-based one - Made HttpClient backend **configurable at runtime** via constructor arguments and `-httpclient=...` CLI option (for zen, zenserver, and tests) - Extended HttpClient test suite to cover multipart/content-range scenarios ### Unix Domain Socket Support - Added Unix domain socket support to **httpasio** (server side) - Added Unix domain socket support to **HttpClient** - Added Unix domain socket support to **HttpWsClient** (WebSocket client) - Templatized `HttpServerConnectionT` and `WsAsioConnectionT` to handle TCP, Unix, and SSL sockets uniformly via `if constexpr` dispatch ### HTTPS Support - Added **preliminary HTTPS support to httpasio** (for Mac/Linux via OpenSSL) - Added **basic HTTPS support for http.sys** (Windows) - Implemented HTTPS test for httpasio - Split `InitializeServer` into smaller sub-functions for http.sys ### Other Notable Changes - Improved **zenhttp-test stability** with dynamic port allocation - Enhanced port retry logic in http.sys (handles ERROR_ACCESS_DENIED) - Fatal signal/exception handlers for backtrace generation in tests - Added `zen bench http` subcommand to exercise network + HTTP client/server communication stack --- src/zenhttp/httpserver.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/zenhttp/httpserver.cpp') diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index 9bae95690..1a0018908 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -1044,13 +1044,16 @@ HttpServer::OnGetExternalHost() const std::string HttpServer::GetServiceUri(const HttpService* Service) const { + const char* Scheme = (m_EffectiveHttpsPort > 0) ? "https" : "http"; + int Port = (m_EffectiveHttpsPort > 0) ? m_EffectiveHttpsPort : m_EffectivePort; + if (Service) { - return fmt::format("http://{}:{}{}", m_ExternalHost, m_EffectivePort, Service->BaseUri()); + return fmt::format("{}://{}:{}{}", Scheme, m_ExternalHost, Port, Service->BaseUri()); } else { - return fmt::format("http://{}:{}", m_ExternalHost, m_EffectivePort); + return fmt::format("{}://{}:{}", Scheme, m_ExternalHost, Port); } } @@ -1152,9 +1155,13 @@ CreateHttpServerClass(const std::string_view ServerClass, const HttpServerConfig if (ServerClass == "asio"sv) { ZEN_INFO("using asio HTTP server implementation") - return CreateHttpAsioServer(AsioConfig{.ThreadCount = Config.ThreadCount, - .ForceLoopback = Config.ForceLoopback, - .IsDedicatedServer = Config.IsDedicatedServer}); + return CreateHttpAsioServer(AsioConfig { + .ThreadCount = Config.ThreadCount, .ForceLoopback = Config.ForceLoopback, .IsDedicatedServer = Config.IsDedicatedServer, + .UnixSocketPath = Config.UnixSocketPath, +#if ZEN_USE_OPENSSL + .HttpsPort = Config.HttpsPort, .CertFile = Config.CertFile, .KeyFile = Config.KeyFile, +#endif + }); } #if ZEN_WITH_HTTPSYS else if (ServerClass == "httpsys"sv) @@ -1165,7 +1172,11 @@ CreateHttpServerClass(const std::string_view ServerClass, const HttpServerConfig .IsAsyncResponseEnabled = Config.HttpSys.IsAsyncResponseEnabled, .IsRequestLoggingEnabled = Config.HttpSys.IsRequestLoggingEnabled, .IsDedicatedServer = Config.IsDedicatedServer, - .ForceLoopback = Config.ForceLoopback})); + .ForceLoopback = Config.ForceLoopback, + .HttpsPort = Config.HttpSys.HttpsPort, + .CertThumbprint = Config.HttpSys.CertThumbprint, + .CertStoreName = Config.HttpSys.CertStoreName, + .HttpsOnly = Config.HttpSys.HttpsOnly})); } #endif else if (ServerClass == "null"sv) -- cgit v1.2.3