@@ -156,6 +156,61 @@ static int ConvertListEntryToMap(const list_entry_t& list_entry, const duckdb::V
156
156
return result.size ();
157
157
}
158
158
159
+
160
+
161
+ std::string headers_to_string (const duckdb_httplib_openssl::Headers& headers) {
162
+ std::string result = " {" ;
163
+
164
+ for (const auto & [key, value] : headers) {
165
+ // Convert ci string to regular string by converting to lowercase in-place
166
+ std::string lower_key = key;
167
+ std::transform (lower_key.begin (), lower_key.end (), lower_key.begin (),
168
+ [](unsigned char c){ return std::tolower (c); });
169
+
170
+ result += " \" " + escape_json (lower_key) + " \" :\" " + escape_json (value) + " \" ," ;
171
+ }
172
+
173
+ if (result.length () > 1 ) {
174
+ result.pop_back (); // Remove trailing comma
175
+ }
176
+ result += " }" ;
177
+
178
+ return result;
179
+ }
180
+
181
+
182
+ static void HTTPHeadRequestFunction (DataChunk &args, ExpressionState &state, Vector &result) {
183
+ D_ASSERT (args.data .size () == 1 );
184
+
185
+ UnaryExecutor::Execute<string_t , string_t >(args.data [0 ], result, args.size (), [&](string_t input) {
186
+ std::string url = input.GetString ();
187
+
188
+ // Use helper to setup client and parse URL
189
+ auto client_and_path = SetupHttpClient (url);
190
+ auto &client = client_and_path.first ;
191
+ auto &path = client_and_path.second ;
192
+
193
+ // Make the GET request
194
+ auto res = client.Head (path.c_str ());
195
+ auto headers = headers_to_string (res->headers );
196
+ if (res) {
197
+ std::string response = StringUtil::Format (
198
+ " { \" status\" : %i, \" reason\" : \" %s\" , \" headers\" : \" %s\" }" ,
199
+ res->status ,
200
+ escape_json (res->reason ),
201
+ escape_json (headers)
202
+ );
203
+ return StringVector::AddString (result, response);
204
+ } else {
205
+ std::string response = StringUtil::Format (
206
+ " { \" status\" : %i, \" reason\" : \" %s\" , \" headers\" : \" %s\" }" ,
207
+ -1 , GetHttpErrorMessage (res, " HEAD" ), " "
208
+ );
209
+ return StringVector::AddString (result, response);
210
+ }
211
+ });
212
+ }
213
+
159
214
static void HTTPGetRequestFunction (DataChunk &args, ExpressionState &state, Vector &result) {
160
215
D_ASSERT (args.data .size () == 1 );
161
216
@@ -303,6 +358,10 @@ static void HTTPPostFormRequestFunction(DataChunk &args, ExpressionState &state,
303
358
304
359
305
360
static void LoadInternal (DatabaseInstance &instance) {
361
+ ScalarFunctionSet http_head (" http_head" );
362
+ http_head.AddFunction (ScalarFunction ({LogicalType::VARCHAR}, LogicalType::JSON (), HTTPHeadRequestFunction));
363
+ ExtensionUtil::RegisterFunction (instance, http_head);
364
+
306
365
ScalarFunctionSet http_get (" http_get" );
307
366
http_get.AddFunction (ScalarFunction ({LogicalType::VARCHAR}, LogicalType::JSON (), HTTPGetRequestFunction));
308
367
http_get.AddFunction (ScalarFunction (
@@ -358,4 +417,3 @@ DUCKDB_EXTENSION_API const char *http_client_version() {
358
417
#ifndef DUCKDB_EXTENSION_MAIN
359
418
#error DUCKDB_EXTENSION_MAIN not defined
360
419
#endif
361
-
0 commit comments