diff --git a/src/http_server.cpp b/src/http_server.cpp index e29fe31..cb85a40 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -9,6 +9,7 @@ #include "utils/serialization.hpp" #include "version.hpp" #include "watcher.hpp" +#include #include #include #include @@ -94,13 +95,17 @@ const HttpServer &HttpServer::Start(ClientContext &context, bool *was_started) { const auto remote_url = GetRemoteUrl(context); const auto port = GetLocalPort(context); + auto &http_util = HTTPUtil::Get(*context.db); + // FIXME - https://github.com/duckdb/duckdb/pull/17655 will remove `unused` + auto http_params = http_util.InitializeParameters(context, "unused"); auto server = GetInstance(context); - server->DoStart(port, remote_url); + server->DoStart(port, remote_url, std::move(http_params)); return *server; } void HttpServer::DoStart(const uint16_t _local_port, - const std::string &_remote_url) { + const std::string &_remote_url, + unique_ptr _http_params) { if (Started()) { throw std::runtime_error("HttpServer already started"); } @@ -108,6 +113,7 @@ void HttpServer::DoStart(const uint16_t _local_port, local_port = _local_port; local_url = StringUtil::Format("http://localhost:%d", local_port); remote_url = _remote_url; + http_params = std::move(_http_params); user_agent = StringUtil::Format("duckdb-ui/%s-%s(%s)", DuckDB::LibraryVersion(), UI_EXTENSION_VERSION, DuckDB::Platform()); @@ -144,6 +150,7 @@ void HttpServer::DoStop() { } ddb_instance.reset(); + http_params = nullptr; remote_url = ""; local_port = 0; } @@ -240,12 +247,34 @@ void HttpServer::HandleGetLocalToken(const httplib::Request &req, } } +// Adapted from +// https://github.com/duckdb/duckdb/blob/1f8b6839ea7864c3e3fb020574f67384cb58124c/src/main/http/http_util.cpp#L129-L147 +// Which is not currently exposed. +void HttpServer::InitClientFromParams(httplib::Client &client) { + auto sec = static_cast(http_params->timeout); + auto usec = static_cast(http_params->timeout_usec); + client.set_keep_alive(true); + client.set_write_timeout(sec, usec); + client.set_read_timeout(sec, usec); + client.set_connection_timeout(sec, usec); + + if (!http_params->http_proxy.empty()) { + client.set_proxy(http_params->http_proxy, + static_cast(http_params->http_proxy_port)); + + if (!http_params->http_proxy_username.empty()) { + client.set_proxy_basic_auth(http_params->http_proxy_username, + http_params->http_proxy_password); + } + } +} + void HttpServer::HandleGet(const httplib::Request &req, httplib::Response &res) { // Create HTTP client to remote URL // TODO: Can this be created once and shared? httplib::Client client(remote_url); - client.set_keep_alive(true); + InitClientFromParams(client); if (IsEnvEnabled("ui_disable_server_certificate_verification")) { client.enable_server_certificate_verification(false); diff --git a/src/include/http_server.hpp b/src/include/http_server.hpp index 041ad01..a22d131 100644 --- a/src/include/http_server.hpp +++ b/src/include/http_server.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #define CPPHTTPLIB_OPENSSL_SUPPORT #include "httplib.hpp" @@ -15,6 +16,7 @@ namespace httplib = duckdb_httplib_openssl; namespace duckdb { +class HTTPParams; class MemoryStream; namespace ui { @@ -40,7 +42,8 @@ class HttpServer { friend class Watcher; // Lifecycle - void DoStart(const uint16_t local_port, const std::string &remote_url); + void DoStart(const uint16_t local_port, const std::string &remote_url, + unique_ptr); void DoStop(); void Run(); void UpdateDatabaseInstance(shared_ptr context_db); @@ -67,6 +70,7 @@ class HttpServer { // Misc shared_ptr LockDatabaseInstance(); + void InitClientFromParams(httplib::Client &); uint16_t local_port; std::string local_url; @@ -77,6 +81,7 @@ class HttpServer { unique_ptr main_thread; unique_ptr event_dispatcher; unique_ptr watcher; + unique_ptr http_params; static unique_ptr server_instance; };