From f6ed5fc60f0fe92bcd3bdf53f9b30e353f79181e Mon Sep 17 00:00:00 2001 From: yhirose Date: Sat, 14 Mar 2026 18:38:34 -0400 Subject: [PATCH] Add SSL support for proxy connections in open_stream and corresponding test --- README-stream.md | 4 ++-- httplib.h | 8 ++++++++ test/test_proxy.cc | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/README-stream.md b/README-stream.md index 851fd38..b7f4162 100644 --- a/README-stream.md +++ b/README-stream.md @@ -45,7 +45,7 @@ cpp-httplib provides multiple API layers for different use cases: ```text ┌─────────────────────────────────────────────┐ -│ SSEClient (planned) │ ← SSE-specific, parsed events +│ SSEClient │ ← SSE-specific, parsed events │ - on_message(), on_event() │ │ - Auto-reconnect, Last-Event-ID │ ├─────────────────────────────────────────────┤ @@ -61,7 +61,7 @@ cpp-httplib provides multiple API layers for different use cases: | Use Case | Recommended API | |----------|----------------| -| SSE with auto-reconnect | SSEClient (planned) or `ssecli-stream.cc` example | +| SSE with auto-reconnect | `SSEClient` (see [README-sse.md](README-sse.md)) | | LLM streaming (JSON Lines) | `stream::Get()` | | Large file download | `stream::Get()` or `open_stream()` | | Reverse proxy | `open_stream()` | diff --git a/httplib.h b/httplib.h index 45a2fbe..d84ca92 100644 --- a/httplib.h +++ b/httplib.h @@ -12413,6 +12413,7 @@ ClientImpl::open_stream(const std::string &method, const std::string &path, handle.response = detail::make_unique(); handle.error = Error::Success; + auto start_time = std::chrono::steady_clock::now(); auto query_path = params.empty() ? path : append_query_params(path, params); handle.connection_ = detail::make_unique(); @@ -12446,6 +12447,13 @@ ClientImpl::open_stream(const std::string &method, const std::string &path, if (is_ssl()) { auto &scli = static_cast(*this); if (!proxy_host_.empty() && proxy_port_ != -1) { + auto success = false; + if (!scli.connect_with_proxy(socket_, start_time, *handle.response, + success, handle.error)) { + if (!success) { handle.response.reset(); } + return handle; + } + if (!scli.initialize_ssl(socket_, handle.error)) { handle.response.reset(); return handle; diff --git a/test/test_proxy.cc b/test/test_proxy.cc index e878647..5f43c20 100644 --- a/test/test_proxy.cc +++ b/test/test_proxy.cc @@ -344,3 +344,25 @@ TEST(KeepAliveTest, SSLWithDigest) { KeepAliveTest(cli, false); } #endif + +// ---------------------------------------------------------------------------- + +#ifdef CPPHTTPLIB_SSL_ENABLED +TEST(ProxyTest, SSLOpenStream) { + SSLClient cli("nghttp2.org"); + cli.set_proxy("localhost", 3128); + cli.set_proxy_basic_auth("hello", "world"); + + auto handle = cli.open_stream("GET", "/httpbin/get"); + ASSERT_TRUE(handle.response); + EXPECT_EQ(StatusCode::OK_200, handle.response->status); + + std::string body; + char buf[8192]; + ssize_t n; + while ((n = handle.read(buf, sizeof(buf))) > 0) { + body.append(buf, static_cast(n)); + } + EXPECT_FALSE(body.empty()); +} +#endif