Skip to content

Commit d8b7a91

Browse files
authored
Merge pull request #1 from quackscience/refactor
Refactor and Deduplicate functions
2 parents 4cddecc + abcde70 commit d8b7a91

File tree

1 file changed

+90
-133
lines changed

1 file changed

+90
-133
lines changed

src/http_client_extension.cpp

Lines changed: 90 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -15,89 +15,103 @@
1515

1616
namespace duckdb {
1717

18+
// Helper function to parse URL and setup client
19+
static std::pair<duckdb_httplib_openssl::Client, std::string> SetupHttpClient(const std::string &url) {
20+
std::string scheme, domain, path;
21+
size_t pos = url.find("://");
22+
std::string mod_url = url;
23+
if (pos != std::string::npos) {
24+
scheme = mod_url.substr(0, pos);
25+
mod_url.erase(0, pos + 3);
26+
}
27+
28+
pos = mod_url.find("/");
29+
if (pos != std::string::npos) {
30+
domain = mod_url.substr(0, pos);
31+
path = mod_url.substr(pos);
32+
} else {
33+
domain = mod_url;
34+
path = "/";
35+
}
36+
37+
// Create client and set a reasonable timeout (e.g., 10 seconds)
38+
duckdb_httplib_openssl::Client client(domain.c_str());
39+
client.set_read_timeout(10, 0); // 10 seconds
40+
client.set_follow_location(true); // Follow redirects
41+
42+
return std::make_pair(std::move(client), path);
43+
}
44+
45+
static void HandleHttpError(const duckdb_httplib_openssl::Result &res, const std::string &request_type) {
46+
std::string err_message = "HTTP " + request_type + " request failed. ";
47+
48+
switch (res.error()) {
49+
case duckdb_httplib_openssl::Error::Connection:
50+
err_message += "Connection error.";
51+
break;
52+
case duckdb_httplib_openssl::Error::BindIPAddress:
53+
err_message += "Failed to bind IP address.";
54+
break;
55+
case duckdb_httplib_openssl::Error::Read:
56+
err_message += "Error reading response.";
57+
break;
58+
case duckdb_httplib_openssl::Error::Write:
59+
err_message += "Error writing request.";
60+
break;
61+
case duckdb_httplib_openssl::Error::ExceedRedirectCount:
62+
err_message += "Too many redirects.";
63+
break;
64+
case duckdb_httplib_openssl::Error::Canceled:
65+
err_message += "Request was canceled.";
66+
break;
67+
case duckdb_httplib_openssl::Error::SSLConnection:
68+
err_message += "SSL connection failed.";
69+
break;
70+
case duckdb_httplib_openssl::Error::SSLLoadingCerts:
71+
err_message += "Failed to load SSL certificates.";
72+
break;
73+
case duckdb_httplib_openssl::Error::SSLServerVerification:
74+
err_message += "SSL server verification failed.";
75+
break;
76+
case duckdb_httplib_openssl::Error::UnsupportedMultipartBoundaryChars:
77+
err_message += "Unsupported characters in multipart boundary.";
78+
break;
79+
case duckdb_httplib_openssl::Error::Compression:
80+
err_message += "Error during compression.";
81+
break;
82+
default:
83+
err_message += "Unknown error.";
84+
break;
85+
}
86+
throw std::runtime_error(err_message);
87+
}
88+
89+
1890
static void HTTPGetRequestFunction(DataChunk &args, ExpressionState &state, Vector &result) {
1991
D_ASSERT(args.data.size() == 1);
2092

2193
UnaryExecutor::Execute<string_t, string_t>(args.data[0], result, args.size(), [&](string_t input) {
2294
std::string url = input.GetString();
2395

24-
// Parse the URL to extract the domain and path
25-
std::string scheme, domain, path;
26-
size_t pos = url.find("://");
27-
if (pos != std::string::npos) {
28-
scheme = url.substr(0, pos);
29-
url.erase(0, pos + 3);
30-
}
31-
32-
pos = url.find("/");
33-
if (pos != std::string::npos) {
34-
domain = url.substr(0, pos);
35-
path = url.substr(pos);
36-
} else {
37-
domain = url;
38-
path = "/";
39-
}
40-
41-
// Create client and set a reasonable timeout (e.g., 10 seconds)
42-
duckdb_httplib_openssl::Client client(domain.c_str());
43-
client.set_read_timeout(10, 0); // 10 seconds
44-
45-
// Follow redirects
46-
client.set_follow_location(true);
96+
// Use helper to setup client and parse URL
97+
auto client_and_path = SetupHttpClient(url);
98+
auto &client = client_and_path.first;
99+
auto &path = client_and_path.second;
47100

48101
// Make the GET request
49102
auto res = client.Get(path.c_str());
50103
if (res) {
51104
if (res->status == 200) {
52105
return StringVector::AddString(result, res->body);
53106
} else {
54-
throw std::runtime_error("HTTP error: " + std::to_string(res->status) + " - " + res->reason);
107+
throw std::runtime_error("HTTP GET error: " + std::to_string(res->status) + " - " + res->reason);
55108
}
56109
} else {
57-
// Handle the error case
58-
std::string err_message = "HTTP request failed. ";
59-
60-
// Convert httplib error codes to a descriptive message
61-
switch (res.error()) {
62-
case duckdb_httplib_openssl::Error::Connection:
63-
err_message += "Connection error.";
64-
break;
65-
case duckdb_httplib_openssl::Error::BindIPAddress:
66-
err_message += "Failed to bind IP address.";
67-
break;
68-
case duckdb_httplib_openssl::Error::Read:
69-
err_message += "Error reading response.";
70-
break;
71-
case duckdb_httplib_openssl::Error::Write:
72-
err_message += "Error writing request.";
73-
break;
74-
case duckdb_httplib_openssl::Error::ExceedRedirectCount:
75-
err_message += "Too many redirects.";
76-
break;
77-
case duckdb_httplib_openssl::Error::Canceled:
78-
err_message += "Request was canceled.";
79-
break;
80-
case duckdb_httplib_openssl::Error::SSLConnection:
81-
err_message += "SSL connection failed.";
82-
break;
83-
case duckdb_httplib_openssl::Error::SSLLoadingCerts:
84-
err_message += "Failed to load SSL certificates.";
85-
break;
86-
case duckdb_httplib_openssl::Error::SSLServerVerification:
87-
err_message += "SSL server verification failed.";
88-
break;
89-
case duckdb_httplib_openssl::Error::UnsupportedMultipartBoundaryChars:
90-
err_message += "Unsupported characters in multipart boundary.";
91-
break;
92-
case duckdb_httplib_openssl::Error::Compression:
93-
err_message += "Error during compression.";
94-
break;
95-
default:
96-
err_message += "Unknown error.";
97-
break;
98-
}
99-
throw std::runtime_error(err_message);
110+
// Handle errors
111+
HandleHttpError(res, "GET");
100112
}
113+
// Ensure a return value in case of an error
114+
return string_t();
101115
});
102116
}
103117

@@ -113,28 +127,10 @@ static void HTTPPostRequestFunction(DataChunk &args, ExpressionState &state, Vec
113127
[&](string_t url, string_t headers, string_t body) {
114128
std::string url_str = url.GetString();
115129

116-
// Parse the URL to extract the domain and path
117-
std::string scheme, domain, path;
118-
size_t pos = url_str.find("://");
119-
if (pos != std::string::npos) {
120-
scheme = url_str.substr(0, pos);
121-
url_str.erase(0, pos + 3);
122-
}
123-
124-
pos = url_str.find("/");
125-
if (pos != std::string::npos) {
126-
domain = url_str.substr(0, pos);
127-
path = url_str.substr(pos);
128-
} else {
129-
domain = url_str;
130-
path = "/";
131-
}
132-
133-
// Create the client and set a timeout (e.g., 10 seconds)
134-
duckdb_httplib_openssl::Client client(domain.c_str());
135-
client.set_read_timeout(10, 0); // 10 seconds
136-
// Follow redirects
137-
client.set_follow_location(true);
130+
// Use helper to setup client and parse URL
131+
auto client_and_path = SetupHttpClient(url_str);
132+
auto &client = client_and_path.first;
133+
auto &path = client_and_path.second;
138134

139135
// Prepare headers
140136
duckdb_httplib_openssl::Headers header_map;
@@ -160,53 +156,14 @@ static void HTTPPostRequestFunction(DataChunk &args, ExpressionState &state, Vec
160156
if (res->status == 200) {
161157
return StringVector::AddString(result, res->body);
162158
} else {
163-
throw std::runtime_error("HTTP error: " + std::to_string(res->status) + " - " + res->reason);
159+
throw std::runtime_error("HTTP POST error: " + std::to_string(res->status) + " - " + res->reason);
164160
}
165161
} else {
166-
// Handle the error case
167-
std::string err_message = "HTTP POST request failed. ";
168-
169-
// Convert httplib error codes to a descriptive message
170-
switch (res.error()) {
171-
case duckdb_httplib_openssl::Error::Connection:
172-
err_message += "Connection error.";
173-
break;
174-
case duckdb_httplib_openssl::Error::BindIPAddress:
175-
err_message += "Failed to bind IP address.";
176-
break;
177-
case duckdb_httplib_openssl::Error::Read:
178-
err_message += "Error reading response.";
179-
break;
180-
case duckdb_httplib_openssl::Error::Write:
181-
err_message += "Error writing request.";
182-
break;
183-
case duckdb_httplib_openssl::Error::ExceedRedirectCount:
184-
err_message += "Too many redirects.";
185-
break;
186-
case duckdb_httplib_openssl::Error::Canceled:
187-
err_message += "Request was canceled.";
188-
break;
189-
case duckdb_httplib_openssl::Error::SSLConnection:
190-
err_message += "SSL connection failed.";
191-
break;
192-
case duckdb_httplib_openssl::Error::SSLLoadingCerts:
193-
err_message += "Failed to load SSL certificates.";
194-
break;
195-
case duckdb_httplib_openssl::Error::SSLServerVerification:
196-
err_message += "SSL server verification failed.";
197-
break;
198-
case duckdb_httplib_openssl::Error::UnsupportedMultipartBoundaryChars:
199-
err_message += "Unsupported characters in multipart boundary.";
200-
break;
201-
case duckdb_httplib_openssl::Error::Compression:
202-
err_message += "Error during compression.";
203-
break;
204-
default:
205-
err_message += "Unknown error.";
206-
break;
207-
}
208-
throw std::runtime_error(err_message);
162+
// Handle errors
163+
HandleHttpError(res, "POST");
209164
}
165+
// Ensure a return value in case of an error
166+
return string_t();
210167
});
211168
}
212169

0 commit comments

Comments
 (0)