Add support for http_proxy from DuckDB

This commit is contained in:
Yves
2025-05-26 11:24:03 +02:00
parent 763e521a99
commit c9d93eee2e
2 changed files with 38 additions and 4 deletions

View File

@@ -9,6 +9,7 @@
#include "utils/serialization.hpp" #include "utils/serialization.hpp"
#include "version.hpp" #include "version.hpp"
#include "watcher.hpp" #include "watcher.hpp"
#include <duckdb/common/http_util.hpp>
#include <duckdb/common/serializer/binary_serializer.hpp> #include <duckdb/common/serializer/binary_serializer.hpp>
#include <duckdb/common/serializer/memory_stream.hpp> #include <duckdb/common/serializer/memory_stream.hpp>
#include <duckdb/main/attached_database.hpp> #include <duckdb/main/attached_database.hpp>
@@ -94,13 +95,17 @@ const HttpServer &HttpServer::Start(ClientContext &context, bool *was_started) {
const auto remote_url = GetRemoteUrl(context); const auto remote_url = GetRemoteUrl(context);
const auto port = GetLocalPort(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); auto server = GetInstance(context);
server->DoStart(port, remote_url); server->DoStart(port, remote_url, std::move(http_params));
return *server; return *server;
} }
void HttpServer::DoStart(const uint16_t _local_port, void HttpServer::DoStart(const uint16_t _local_port,
const std::string &_remote_url) { const std::string &_remote_url,
unique_ptr<HTTPParams> _http_params) {
if (Started()) { if (Started()) {
throw std::runtime_error("HttpServer already 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_port = _local_port;
local_url = StringUtil::Format("http://localhost:%d", local_port); local_url = StringUtil::Format("http://localhost:%d", local_port);
remote_url = _remote_url; remote_url = _remote_url;
http_params = std::move(_http_params);
user_agent = user_agent =
StringUtil::Format("duckdb-ui/%s-%s(%s)", DuckDB::LibraryVersion(), StringUtil::Format("duckdb-ui/%s-%s(%s)", DuckDB::LibraryVersion(),
UI_EXTENSION_VERSION, DuckDB::Platform()); UI_EXTENSION_VERSION, DuckDB::Platform());
@@ -144,6 +150,7 @@ void HttpServer::DoStop() {
} }
ddb_instance.reset(); ddb_instance.reset();
http_params = nullptr;
remote_url = ""; remote_url = "";
local_port = 0; 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<time_t>(http_params->timeout);
auto usec = static_cast<time_t>(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<int>(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, void HttpServer::HandleGet(const httplib::Request &req,
httplib::Response &res) { httplib::Response &res) {
// Create HTTP client to remote URL // Create HTTP client to remote URL
// TODO: Can this be created once and shared? // TODO: Can this be created once and shared?
httplib::Client client(remote_url); httplib::Client client(remote_url);
client.set_keep_alive(true); InitClientFromParams(client);
if (IsEnvEnabled("ui_disable_server_certificate_verification")) { if (IsEnvEnabled("ui_disable_server_certificate_verification")) {
client.enable_server_certificate_verification(false); client.enable_server_certificate_verification(false);

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <duckdb.hpp> #include <duckdb.hpp>
#include <duckdb/common/http_util.hpp>
#define CPPHTTPLIB_OPENSSL_SUPPORT #define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.hpp" #include "httplib.hpp"
@@ -15,6 +16,7 @@
namespace httplib = duckdb_httplib_openssl; namespace httplib = duckdb_httplib_openssl;
namespace duckdb { namespace duckdb {
class HTTPParams;
class MemoryStream; class MemoryStream;
namespace ui { namespace ui {
@@ -40,7 +42,8 @@ private:
friend class Watcher; friend class Watcher;
// Lifecycle // 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<HTTPParams>);
void DoStop(); void DoStop();
void Run(); void Run();
void UpdateDatabaseInstance(shared_ptr<DatabaseInstance> context_db); void UpdateDatabaseInstance(shared_ptr<DatabaseInstance> context_db);
@@ -67,6 +70,7 @@ private:
// Misc // Misc
shared_ptr<DatabaseInstance> LockDatabaseInstance(); shared_ptr<DatabaseInstance> LockDatabaseInstance();
void InitClientFromParams(httplib::Client &);
uint16_t local_port; uint16_t local_port;
std::string local_url; std::string local_url;
@@ -77,6 +81,7 @@ private:
unique_ptr<std::thread> main_thread; unique_ptr<std::thread> main_thread;
unique_ptr<EventDispatcher> event_dispatcher; unique_ptr<EventDispatcher> event_dispatcher;
unique_ptr<Watcher> watcher; unique_ptr<Watcher> watcher;
unique_ptr<HTTPParams> http_params;
static unique_ptr<HttpServer> server_instance; static unique_ptr<HttpServer> server_instance;
}; };