77#include < sys/stat.h>
88#include " duckdb/common/exception/http_exception.hpp"
99
10- #ifndef EMSCRIPTEN
11- #include " httpfs_curl_client.hpp"
12- #endif
10+ #define CHECK_CURL_OK (expr ) D_ASSERT((expr) == CURLE_OK)
1311
1412namespace duckdb {
1513
@@ -91,11 +89,11 @@ CURLHandle::CURLHandle(const string &token, const string &cert_path) {
9189 throw InternalException (" Failed to initialize curl" );
9290 }
9391 if (!token.empty ()) {
94- curl_easy_setopt (curl, CURLOPT_XOAUTH2_BEARER, token.c_str ());
95- curl_easy_setopt (curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
92+ CHECK_CURL_OK ( curl_easy_setopt (curl, CURLOPT_XOAUTH2_BEARER, token.c_str () ));
93+ CHECK_CURL_OK ( curl_easy_setopt (curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER) );
9694 }
9795 if (!cert_path.empty ()) {
98- curl_easy_setopt (curl, CURLOPT_CAINFO, cert_path.c_str ());
96+ CHECK_CURL_OK ( curl_easy_setopt (curl, CURLOPT_CAINFO, cert_path.c_str () ));
9997 }
10098}
10199
@@ -110,7 +108,7 @@ struct RequestInfo {
110108 std::vector<HTTPHeaders> header_collection;
111109};
112110
113- static idx_t httpfs_client_count = 0 ;
111+ static std::atomic< idx_t > httpfs_client_count = 0 ;
114112
115113class HTTPFSCurlClient : public HTTPClient {
116114public:
@@ -129,45 +127,48 @@ class HTTPFSCurlClient : public HTTPClient {
129127
130128 // set curl options
131129 // follow redirects
132- curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L );
130+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L ) );
133131
134132 // Curl re-uses connections by default
135133 if (!http_params.keep_alive ) {
136- curl_easy_setopt (*curl, CURLOPT_FORBID_REUSE, 1L );
134+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_FORBID_REUSE, 1L ) );
137135 }
138136
139137 if (http_params.enable_curl_server_cert_verification ) {
140- curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYPEER, 1L ); // Verify the cert
141- curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYHOST, 2L ); // Verify that the cert matches the hostname
138+ CHECK_CURL_OK (curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYPEER, 1L )); // Verify the cert
139+ CHECK_CURL_OK (
140+ curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYHOST, 2L )); // Verify that the cert matches the hostname
142141 } else {
143- curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYPEER, 0L ); // Override default, don't verify the cert
144- curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYHOST,
145- 0L ); // Override default, don't verify that the cert matches the hostname
142+ CHECK_CURL_OK (
143+ curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYPEER, 0L )); // Override default, don't verify the cert
144+ CHECK_CURL_OK (curl_easy_setopt (*curl, CURLOPT_SSL_VERIFYHOST,
145+ 0L )); // Override default, don't verify that the cert matches the hostname
146146 }
147147
148148 // set read timeout
149- curl_easy_setopt (*curl, CURLOPT_TIMEOUT, http_params.timeout );
149+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_TIMEOUT, http_params.timeout ) );
150150 // set connection timeout
151- curl_easy_setopt (*curl, CURLOPT_CONNECTTIMEOUT, http_params.timeout );
151+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_CONNECTTIMEOUT, http_params.timeout ) );
152152 // accept content as-is (i.e no decompressing)
153- curl_easy_setopt (*curl, CURLOPT_ACCEPT_ENCODING, " identity" );
153+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_ACCEPT_ENCODING, " identity" ) );
154154 // follow redirects
155- curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L );
155+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L ) );
156156
157157 // define the header callback
158- curl_easy_setopt (*curl, CURLOPT_HEADERFUNCTION, RequestHeaderCallback);
159- curl_easy_setopt (*curl, CURLOPT_HEADERDATA, &request_info->header_collection );
158+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HEADERFUNCTION, RequestHeaderCallback) );
159+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HEADERDATA, &request_info->header_collection ) );
160160 // define the write data callback (for get requests)
161- curl_easy_setopt (*curl, CURLOPT_WRITEFUNCTION, RequestWriteCallback);
162- curl_easy_setopt (*curl, CURLOPT_WRITEDATA, &request_info->body );
161+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_WRITEFUNCTION, RequestWriteCallback) );
162+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_WRITEDATA, &request_info->body ) );
163163
164164 if (!http_params.http_proxy .empty ()) {
165- curl_easy_setopt (*curl, CURLOPT_PROXY,
166- StringUtil::Format (" %s:%s" , http_params.http_proxy , http_params.http_proxy_port ).c_str ());
165+ CHECK_CURL_OK (curl_easy_setopt (
166+ *curl, CURLOPT_PROXY,
167+ StringUtil::Format (" %s:%s" , http_params.http_proxy , http_params.http_proxy_port ).c_str ()));
167168
168169 if (!http_params.http_proxy_username .empty ()) {
169- curl_easy_setopt (*curl, CURLOPT_PROXYUSERNAME, http_params.http_proxy_username .c_str ());
170- curl_easy_setopt (*curl, CURLOPT_PROXYPASSWORD, http_params.http_proxy_password .c_str ());
170+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_PROXYUSERNAME, http_params.http_proxy_username .c_str () ));
171+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_PROXYPASSWORD, http_params.http_proxy_password .c_str () ));
171172 }
172173 }
173174 }
@@ -191,9 +192,9 @@ class HTTPFSCurlClient : public HTTPClient {
191192 CURLcode res;
192193 {
193194 // If the same handle served a HEAD request, we must set NOBODY back to 0L to request content again
194- curl_easy_setopt (*curl, CURLOPT_NOBODY, 0L );
195- curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str ());
196- curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr );
195+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_NOBODY, 0L ) );
196+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str () ));
197+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr ) );
197198 res = curl->Execute ();
198199 }
199200
@@ -237,15 +238,15 @@ class HTTPFSCurlClient : public HTTPClient {
237238
238239 CURLcode res;
239240 {
240- curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str ());
241+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str () ));
241242 // Perform PUT
242- curl_easy_setopt (*curl, CURLOPT_CUSTOMREQUEST, " PUT" );
243+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_CUSTOMREQUEST, " PUT" ) );
243244 // Include PUT body
244- curl_easy_setopt (*curl, CURLOPT_POSTFIELDS, const_char_ptr_cast (info.buffer_in ));
245- curl_easy_setopt (*curl, CURLOPT_POSTFIELDSIZE, info.buffer_in_len );
245+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_POSTFIELDS, const_char_ptr_cast (info.buffer_in ) ));
246+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_POSTFIELDSIZE, info.buffer_in_len ) );
246247
247248 // Apply headers
248- curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr );
249+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr ) );
249250
250251 res = curl->Execute ();
251252 }
@@ -271,14 +272,14 @@ class HTTPFSCurlClient : public HTTPClient {
271272 CURLcode res;
272273 {
273274 // Set URL
274- curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str ());
275+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str () ));
275276
276277 // Perform HEAD request instead of GET
277- curl_easy_setopt (*curl, CURLOPT_NOBODY, 1L );
278- curl_easy_setopt (*curl, CURLOPT_HTTPGET, 0L );
278+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_NOBODY, 1L ) );
279+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPGET, 0L ) );
279280
280281 // Add headers if any
281- curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr );
282+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr ) );
282283
283284 // Execute HEAD request
284285 res = curl->Execute ();
@@ -304,16 +305,16 @@ class HTTPFSCurlClient : public HTTPClient {
304305 CURLcode res;
305306 {
306307 // Set URL
307- curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str ());
308+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str () ));
308309
309310 // Set DELETE request method
310- curl_easy_setopt (*curl, CURLOPT_CUSTOMREQUEST, " DELETE" );
311+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_CUSTOMREQUEST, " DELETE" ) );
311312
312313 // Follow redirects
313- curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L );
314+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_FOLLOWLOCATION, 1L ) );
314315
315316 // Add headers if any
316- curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr );
317+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr ) );
317318
318319 // Execute DELETE request
319320 res = curl->Execute ();
@@ -342,15 +343,15 @@ class HTTPFSCurlClient : public HTTPClient {
342343
343344 CURLcode res;
344345 {
345- curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str ());
346- curl_easy_setopt (*curl, CURLOPT_POST, 1L );
346+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_URL, request_info->url .c_str () ));
347+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_POST, 1L ) );
347348
348349 // Set POST body
349- curl_easy_setopt (*curl, CURLOPT_POSTFIELDS, const_char_ptr_cast (info.buffer_in ));
350- curl_easy_setopt (*curl, CURLOPT_POSTFIELDSIZE, info.buffer_in_len );
350+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_POSTFIELDS, const_char_ptr_cast (info.buffer_in ) ));
351+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_POSTFIELDSIZE, info.buffer_in_len ) );
351352
352353 // Add headers if any
353- curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr );
354+ CHECK_CURL_OK ( curl_easy_setopt (*curl, CURLOPT_HTTPHEADER, curl_headers ? curl_headers.headers : nullptr ) );
354355
355356 // Execute POST request
356357 res = curl->Execute ();
@@ -430,11 +431,6 @@ class HTTPFSCurlClient : public HTTPClient {
430431 optional_ptr<HTTPState> state;
431432 unique_ptr<RequestInfo> request_info;
432433
433- static std::mutex &GetRefLock () {
434- static std::mutex mtx;
435- return mtx;
436- }
437-
438434 static void InitCurlGlobal () {
439435 GetRefLock ();
440436 if (httpfs_client_count == 0 ) {
0 commit comments