Skip to content

Commit 29771a0

Browse files
authored
vendor : update cpp-httplib to 0.39.0 (ggml-org#20933)
1 parent 42ebce3 commit 29771a0

3 files changed

Lines changed: 109 additions & 48 deletions

File tree

scripts/sync_vendor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66
import subprocess
77

8-
HTTPLIB_VERSION = "refs/tags/v0.38.0"
8+
HTTPLIB_VERSION = "refs/tags/v0.39.0"
99

1010
vendor = {
1111
"https://github.com/nlohmann/json/releases/latest/download/json.hpp": "vendor/nlohmann/json.hpp",

vendor/cpp-httplib/httplib.cpp

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ SSEClient &SSEClient::set_max_reconnect_attempts(int n) {
142142
return *this;
143143
}
144144

145+
SSEClient &SSEClient::set_headers(const Headers &headers) {
146+
std::lock_guard<std::mutex> lock(headers_mutex_);
147+
headers_ = headers;
148+
return *this;
149+
}
150+
145151
bool SSEClient::is_connected() const { return connected_.load(); }
146152

147153
const std::string &SSEClient::last_event_id() const {
@@ -220,7 +226,11 @@ void SSEClient::run_event_loop() {
220226

221227
while (running_.load()) {
222228
// Build headers, including Last-Event-ID if we have one
223-
auto request_headers = headers_;
229+
Headers request_headers;
230+
{
231+
std::lock_guard<std::mutex> lock(headers_mutex_);
232+
request_headers = headers_;
233+
}
224234
if (!last_event_id_.empty()) {
225235
request_headers.emplace("Last-Event-ID", last_event_id_);
226236
}
@@ -239,19 +249,19 @@ void SSEClient::run_event_loop() {
239249
continue;
240250
}
241251

242-
if (result.status() != 200) {
252+
if (result.status() != StatusCode::OK_200) {
243253
connected_.store(false);
244-
// For certain errors, don't reconnect
245-
if (result.status() == 204 || // No Content - server wants us to stop
246-
result.status() == 404 || // Not Found
247-
result.status() == 401 || // Unauthorized
248-
result.status() == 403) { // Forbidden
249-
if (on_error_) { on_error_(Error::Connection); }
254+
if (on_error_) { on_error_(Error::Connection); }
255+
256+
// For certain errors, don't reconnect.
257+
// Note: 401 is intentionally absent so that handlers can refresh
258+
// credentials via set_headers() and let the client reconnect.
259+
if (result.status() == StatusCode::NoContent_204 ||
260+
result.status() == StatusCode::NotFound_404 ||
261+
result.status() == StatusCode::Forbidden_403) {
250262
break;
251263
}
252264

253-
if (on_error_) { on_error_(Error::Connection); }
254-
255265
if (!should_reconnect(reconnect_count)) { break; }
256266
wait_for_reconnect();
257267
reconnect_count++;
@@ -9168,18 +9178,11 @@ void ClientImpl::setup_redirect_client(ClientType &client) {
91689178
client.set_compress(compress_);
91699179
client.set_decompress(decompress_);
91709180

9171-
// Copy authentication settings BEFORE proxy setup
9172-
if (!basic_auth_username_.empty()) {
9173-
client.set_basic_auth(basic_auth_username_, basic_auth_password_);
9174-
}
9175-
if (!bearer_token_auth_token_.empty()) {
9176-
client.set_bearer_token_auth(bearer_token_auth_token_);
9177-
}
9178-
#ifdef CPPHTTPLIB_SSL_ENABLED
9179-
if (!digest_auth_username_.empty()) {
9180-
client.set_digest_auth(digest_auth_username_, digest_auth_password_);
9181-
}
9182-
#endif
9181+
// NOTE: Authentication credentials (basic auth, bearer token, digest auth)
9182+
// are intentionally NOT copied to the redirect client. Per RFC 9110 Section
9183+
// 15.4, credentials must not be forwarded when redirecting to a different
9184+
// host. This function is only called for cross-host redirects; same-host
9185+
// redirects are handled directly in ClientImpl::redirect().
91839186

91849187
// Setup proxy configuration (CRITICAL ORDER - proxy must be set
91859188
// before proxy auth)
@@ -11425,7 +11428,8 @@ void Client::set_follow_location(bool on) {
1142511428

1142611429
void Client::set_path_encode(bool on) { cli_->set_path_encode(on); }
1142711430

11428-
[[deprecated("Use set_path_encode instead")]]
11431+
[[deprecated("Use set_path_encode() instead. "
11432+
"This function will be removed by v1.0.0.")]]
1142911433
void Client::set_url_encode(bool on) {
1143011434
cli_->set_path_encode(on);
1143111435
}
@@ -16330,9 +16334,10 @@ bool WebSocketClient::connect() {
1633016334

1633116335
Error error;
1633216336
sock_ = detail::create_client_socket(
16333-
host_, std::string(), port_, AF_UNSPEC, false, false, nullptr, 5, 0,
16337+
host_, std::string(), port_, address_family_, tcp_nodelay_, ipv6_v6only_,
16338+
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
1633416339
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
16335-
write_timeout_usec_, std::string(), error);
16340+
write_timeout_usec_, interface_, error);
1633616341

1633716342
if (sock_ == INVALID_SOCKET) { return false; }
1633816343

@@ -16398,6 +16403,27 @@ void WebSocketClient::set_websocket_ping_interval(time_t sec) {
1639816403
websocket_ping_interval_sec_ = sec;
1639916404
}
1640016405

16406+
void WebSocketClient::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; }
16407+
16408+
void WebSocketClient::set_address_family(int family) {
16409+
address_family_ = family;
16410+
}
16411+
16412+
void WebSocketClient::set_ipv6_v6only(bool on) { ipv6_v6only_ = on; }
16413+
16414+
void WebSocketClient::set_socket_options(SocketOptions socket_options) {
16415+
socket_options_ = std::move(socket_options);
16416+
}
16417+
16418+
void WebSocketClient::set_connection_timeout(time_t sec, time_t usec) {
16419+
connection_timeout_sec_ = sec;
16420+
connection_timeout_usec_ = usec;
16421+
}
16422+
16423+
void WebSocketClient::set_interface(const std::string &intf) {
16424+
interface_ = intf;
16425+
}
16426+
1640116427
#ifdef CPPHTTPLIB_SSL_ENABLED
1640216428

1640316429
void WebSocketClient::set_ca_cert_path(const std::string &path) {

vendor/cpp-httplib/httplib.h

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#ifndef CPPHTTPLIB_HTTPLIB_H
99
#define CPPHTTPLIB_HTTPLIB_H
1010

11-
#define CPPHTTPLIB_VERSION "0.38.0"
12-
#define CPPHTTPLIB_VERSION_NUM "0x002600"
11+
#define CPPHTTPLIB_VERSION "0.39.0"
12+
#define CPPHTTPLIB_VERSION_NUM "0x002700"
1313

1414
#ifdef _WIN32
1515
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
@@ -1001,8 +1001,8 @@ class DataSink {
10011001

10021002
protected:
10031003
std::streamsize xsputn(const char *s, std::streamsize n) override {
1004-
sink_.write(s, static_cast<size_t>(n));
1005-
return n;
1004+
if (sink_.write(s, static_cast<size_t>(n))) { return n; }
1005+
return 0;
10061006
}
10071007

10081008
private:
@@ -1058,9 +1058,12 @@ make_file_provider(const std::string &name, const std::string &filepath,
10581058

10591059
inline std::pair<size_t, ContentProvider>
10601060
make_file_body(const std::string &filepath) {
1061-
std::ifstream f(filepath, std::ios::binary | std::ios::ate);
1062-
if (!f) { return {0, ContentProvider{}}; }
1063-
auto size = static_cast<size_t>(f.tellg());
1061+
size_t size = 0;
1062+
{
1063+
std::ifstream f(filepath, std::ios::binary | std::ios::ate);
1064+
if (!f) { return {0, ContentProvider{}}; }
1065+
size = static_cast<size_t>(f.tellg());
1066+
}
10641067

10651068
ContentProvider provider = [filepath](size_t offset, size_t length,
10661069
DataSink &sink) -> bool {
@@ -1882,7 +1885,8 @@ class Result {
18821885

18831886
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
18841887
public:
1885-
[[deprecated("Use ssl_backend_error() instead")]]
1888+
[[deprecated("Use ssl_backend_error() instead. "
1889+
"This function will be removed by v1.0.0.")]]
18861890
uint64_t ssl_openssl_error() const {
18871891
return ssl_backend_error_;
18881892
}
@@ -2362,13 +2366,16 @@ class ClientImpl {
23622366

23632367
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
23642368
public:
2365-
[[deprecated("Use load_ca_cert_store() instead")]]
2369+
[[deprecated("Use load_ca_cert_store() instead. "
2370+
"This function will be removed by v1.0.0.")]]
23662371
void set_ca_cert_store(X509_STORE *ca_cert_store);
23672372

2368-
[[deprecated("Use tls::create_ca_store() instead")]]
2373+
[[deprecated("Use tls::create_ca_store() instead. "
2374+
"This function will be removed by v1.0.0.")]]
23692375
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
23702376

2371-
[[deprecated("Use set_server_certificate_verifier(VerifyCallback) instead")]]
2377+
[[deprecated("Use set_server_certificate_verifier(VerifyCallback) instead. "
2378+
"This function will be removed by v1.0.0.")]]
23722379
virtual void set_server_certificate_verifier(
23732380
std::function<SSLVerifierResponse(SSL *ssl)> verifier);
23742381
#endif
@@ -2597,14 +2604,17 @@ class Client {
25972604

25982605
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
25992606
public:
2600-
[[deprecated("Use tls_context() instead")]]
2607+
[[deprecated("Use tls_context() instead. "
2608+
"This function will be removed by v1.0.0.")]]
26012609
SSL_CTX *ssl_context() const;
26022610

2603-
[[deprecated("Use set_session_verifier(session_t) instead")]]
2611+
[[deprecated("Use set_session_verifier(session_t) instead. "
2612+
"This function will be removed by v1.0.0.")]]
26042613
void set_server_certificate_verifier(
26052614
std::function<SSLVerifierResponse(SSL *ssl)> verifier);
26062615

2607-
[[deprecated("Use Result::ssl_backend_error() instead")]]
2616+
[[deprecated("Use Result::ssl_backend_error() instead. "
2617+
"This function will be removed by v1.0.0.")]]
26082618
long get_verify_result() const;
26092619
#endif
26102620
};
@@ -2656,18 +2666,22 @@ class SSLServer : public Server {
26562666
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26572667
public:
26582668
[[deprecated("Use SSLServer(PemMemory) or "
2659-
"SSLServer(ContextSetupCallback) instead")]]
2669+
"SSLServer(ContextSetupCallback) instead. "
2670+
"This constructor will be removed by v1.0.0.")]]
26602671
SSLServer(X509 *cert, EVP_PKEY *private_key,
26612672
X509_STORE *client_ca_cert_store = nullptr);
26622673

2663-
[[deprecated("Use SSLServer(ContextSetupCallback) instead")]]
2674+
[[deprecated("Use SSLServer(ContextSetupCallback) instead. "
2675+
"This constructor will be removed by v1.0.0.")]]
26642676
SSLServer(
26652677
const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback);
26662678

2667-
[[deprecated("Use tls_context() instead")]]
2679+
[[deprecated("Use tls_context() instead. "
2680+
"This function will be removed by v1.0.0.")]]
26682681
SSL_CTX *ssl_context() const;
26692682

2670-
[[deprecated("Use update_certs_pem() instead")]]
2683+
[[deprecated("Use update_certs_pem() instead. "
2684+
"This function will be removed by v1.0.0.")]]
26712685
void update_certs(X509 *cert, EVP_PKEY *private_key,
26722686
X509_STORE *client_ca_cert_store = nullptr);
26732687
#endif
@@ -2752,18 +2766,22 @@ class SSLClient final : public ClientImpl {
27522766

27532767
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
27542768
public:
2755-
[[deprecated("Use SSLClient(host, port, PemMemory) instead")]]
2769+
[[deprecated("Use SSLClient(host, port, PemMemory) instead. "
2770+
"This constructor will be removed by v1.0.0.")]]
27562771
explicit SSLClient(const std::string &host, int port, X509 *client_cert,
27572772
EVP_PKEY *client_key,
27582773
const std::string &private_key_password = std::string());
27592774

2760-
[[deprecated("Use Result::ssl_backend_error() instead")]]
2775+
[[deprecated("Use Result::ssl_backend_error() instead. "
2776+
"This function will be removed by v1.0.0.")]]
27612777
long get_verify_result() const;
27622778

2763-
[[deprecated("Use tls_context() instead")]]
2779+
[[deprecated("Use tls_context() instead. "
2780+
"This function will be removed by v1.0.0.")]]
27642781
SSL_CTX *ssl_context() const;
27652782

2766-
[[deprecated("Use set_session_verifier(session_t) instead")]]
2783+
[[deprecated("Use set_session_verifier(session_t) instead. "
2784+
"This function will be removed by v1.0.0.")]]
27672785
void set_server_certificate_verifier(
27682786
std::function<SSLVerifierResponse(SSL *ssl)> verifier) override;
27692787

@@ -3641,6 +3659,9 @@ class SSEClient {
36413659
SSEClient &set_reconnect_interval(int ms);
36423660
SSEClient &set_max_reconnect_attempts(int n);
36433661

3662+
// Update headers (thread-safe)
3663+
SSEClient &set_headers(const Headers &headers);
3664+
36443665
// State accessors
36453666
bool is_connected() const;
36463667
const std::string &last_event_id() const;
@@ -3665,6 +3686,7 @@ class SSEClient {
36653686
Client &client_;
36663687
std::string path_;
36673688
Headers headers_;
3689+
mutable std::mutex headers_mutex_;
36683690

36693691
// Callbacks
36703692
MessageHandler on_message_;
@@ -3785,6 +3807,12 @@ class WebSocketClient {
37853807
void set_read_timeout(time_t sec, time_t usec = 0);
37863808
void set_write_timeout(time_t sec, time_t usec = 0);
37873809
void set_websocket_ping_interval(time_t sec);
3810+
void set_tcp_nodelay(bool on);
3811+
void set_address_family(int family);
3812+
void set_ipv6_v6only(bool on);
3813+
void set_socket_options(SocketOptions socket_options);
3814+
void set_connection_timeout(time_t sec, time_t usec = 0);
3815+
void set_interface(const std::string &intf);
37883816

37893817
#ifdef CPPHTTPLIB_SSL_ENABLED
37903818
void set_ca_cert_path(const std::string &path);
@@ -3810,6 +3838,13 @@ class WebSocketClient {
38103838
time_t write_timeout_usec_ = CPPHTTPLIB_CLIENT_WRITE_TIMEOUT_USECOND;
38113839
time_t websocket_ping_interval_sec_ =
38123840
CPPHTTPLIB_WEBSOCKET_PING_INTERVAL_SECOND;
3841+
int address_family_ = AF_UNSPEC;
3842+
bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
3843+
bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;
3844+
SocketOptions socket_options_ = nullptr;
3845+
time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
3846+
time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
3847+
std::string interface_;
38133848

38143849
#ifdef CPPHTTPLIB_SSL_ENABLED
38153850
bool is_ssl_ = false;

0 commit comments

Comments
 (0)