Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk_v2/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ set(FOUNDRY_LOCAL_SOURCES
src/exception.cc
src/inferencing/generative/genai_config.cc
src/http/http_client.cc
src/http/curl_transport.cc
src/inferencing/generative/genai_model_instance.cc
src/inferencing/generative/tokenizer.cc
src/logger.cc
Expand Down
11 changes: 7 additions & 4 deletions sdk_v2/cpp/src/download/blob_downloader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
// does not honor SSL_CERT_FILE. On non-Windows builds we install a CurlTransport preconfigured with
// CAInfo (see MakeBlobClientOptions below). Desktop Windows uses the default WinHTTP transport.
#if !defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
#include "http/curl_transport.h"

#include <azure/core/http/curl_transport.hpp>
#endif

Expand All @@ -50,10 +52,11 @@ constexpr size_t kStreamingBufferBytes = 64 * 1024;
Azure::Storage::Blobs::BlobClientOptions MakeBlobClientOptions() {
Azure::Storage::Blobs::BlobClientOptions options;
#if !defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
if (std::string ca_bundle = fl::http::CaBundleFile(); !ca_bundle.empty()) {
Azure::Core::Http::CurlTransportOptions curl_opts;
curl_opts.CAInfo = std::move(ca_bundle);
options.Transport.Transport = std::make_shared<Azure::Core::Http::CurlTransport>(curl_opts);
// Only override the Storage SDK's default transport when a CA bundle is configured.
auto curl_options = fl::http::MakeCurlTransportOptions();
if (!curl_options.CAInfo.empty()) {
options.Transport.Transport =
std::make_shared<Azure::Core::Http::CurlTransport>(curl_options);
}
#endif
return options;
Expand Down
26 changes: 26 additions & 0 deletions sdk_v2/cpp/src/http/curl_transport.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "http/curl_transport.h"

#if !defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)

#include "http/http_client.h"

#include <string>

namespace fl {
namespace http {

Azure::Core::Http::CurlTransportOptions MakeCurlTransportOptions() {
Azure::Core::Http::CurlTransportOptions options;
if (const std::string& ca_bundle = CABundleFilePath(); !ca_bundle.empty()) {
options.CAInfo = ca_bundle;
}

return options;
}

} // namespace http
} // namespace fl

#endif // !FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT
22 changes: 22 additions & 0 deletions sdk_v2/cpp/src/http/curl_transport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once

// Desktop Windows uses the WinHTTP transport and never links libcurl, so the curl transport options
// are only meaningful for the non-WinHTTP (libcurl) builds. Guard the whole header accordingly so
// includers on Windows do not pull in the Azure curl transport dependency.
#if !defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)

#include <azure/core/http/curl_transport.hpp>

namespace fl {
namespace http {

/// Creates libcurl transport options with `CAInfo` populated from `SSL_CERT_FILE` via `CABundleFilePath`.
/// When `SSL_CERT_FILE` is unset, `CAInfo` is empty and libcurl falls back to its compiled-in default.
Azure::Core::Http::CurlTransportOptions MakeCurlTransportOptions();

} // namespace http
} // namespace fl

#endif // !FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT
28 changes: 13 additions & 15 deletions sdk_v2/cpp/src/http/http_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
#if defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
#include <azure/core/http/win_http_transport.hpp>
#else
#include "http/curl_transport.h"

#include <azure/core/http/curl_transport.hpp>
#endif

#include <chrono>
#include <cstdlib>
#include <random>
#include <string>
#include <thread>
Expand All @@ -32,12 +33,14 @@
namespace fl {
namespace http {

std::string CaBundleFile() {
const char* cert_file = std::getenv("SSL_CERT_FILE");
if (cert_file != nullptr && cert_file[0] != '\0') {
return cert_file;
}
return {};
const std::string& CABundleFilePath() {
// SSL_CERT_FILE is fixed for the process lifetime (callers set it before loading the library), so
// read it once and return a reference to the cached path for every request.
static const std::string ca_bundle = [] {
auto cert_file = Utils::GetEnv("SSL_CERT_FILE");
return (cert_file && !cert_file->empty()) ? std::move(*cert_file) : std::string();
}();
Comment thread
skottmckay marked this conversation as resolved.
return ca_bundle;
}

namespace {
Expand All @@ -58,14 +61,9 @@ HttpRawResult HttpRequestRaw(const Azure::Core::Http::HttpMethod& method,
#if defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
WinHttpTransport transport;
#else
// The bundled libcurl does not honor the SSL_CERT_FILE environment variable (it was built with a
// compiled-in default CA path that does not exist on platforms like Android). Explicitly pass the
// CA bundle via CAInfo so the caller-provided trust store is actually used for TLS verification.
CurlTransportOptions curl_opts;
if (std::string ca_bundle = CaBundleFile(); !ca_bundle.empty()) {
curl_opts.CAInfo = std::move(ca_bundle);
}
CurlTransport transport(curl_opts);
// libcurl does not honor SSL_CERT_FILE (its compiled-in default CA path is absent on Android), so
// pass the CA bundle explicitly via CAInfo (see http/curl_transport.h).
CurlTransport transport(MakeCurlTransportOptions());
#endif

// Build the request. For methods with a body (POST), attach a MemoryBodyStream.
Expand Down
13 changes: 7 additions & 6 deletions sdk_v2/cpp/src/http/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ struct HttpRequestOptions {
};

/// Returns the CA bundle file path from the `SSL_CERT_FILE` environment variable, or an empty
/// string when it is unset/empty. The bundled libcurl does not consult `SSL_CERT_FILE`
/// automatically (it was built with a compiled-in default CA path that does not exist on platforms
/// like Android), so every libcurl-based transport we construct — direct requests, file downloads,
/// and the Azure Storage blob client — must pass this explicitly as `CAInfo`. On desktop Windows the
/// WinHTTP transport uses the OS trust store and ignores this.
std::string CaBundleFile();
/// string when it is unset/empty. The value is read once and cached for the process lifetime, so a
/// reference to the cached string is returned (valid until process exit). The bundled libcurl does
/// not consult `SSL_CERT_FILE` automatically (it was built with a compiled-in default CA path that
/// does not exist on platforms like Android), so every libcurl-based transport we construct — direct
/// requests, file downloads, and the Azure Storage blob client — must pass this explicitly as
/// `CAInfo`. On desktop Windows the WinHTTP transport uses the OS trust store and ignores this.
const std::string& CABundleFilePath();

/// Perform an HTTP POST and return status, headers, and body without throwing on non-2xx responses.
/// Transport failures are returned as `status == 0` with the error message in `body`.
Expand Down
13 changes: 5 additions & 8 deletions sdk_v2/cpp/src/http/http_download.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#if defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
#include <azure/core/http/win_http_transport.hpp>
#else
#include "http/curl_transport.h"

#include <azure/core/http/curl_transport.hpp>
#endif

Expand Down Expand Up @@ -43,14 +45,9 @@ bool HttpDownloadFile(const std::string& url,
#if defined(FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT)
WinHttpTransport transport;
#else
// The bundled libcurl does not honor the SSL_CERT_FILE environment variable (it was built with a
// compiled-in default CA path that does not exist on platforms like Android). Explicitly pass the
// CA bundle via CAInfo so the caller-provided trust store is actually used for TLS verification.
CurlTransportOptions curl_opts;
if (std::string ca_bundle = http::CaBundleFile(); !ca_bundle.empty()) {
curl_opts.CAInfo = std::move(ca_bundle);
}
CurlTransport transport(curl_opts);
// libcurl does not honor SSL_CERT_FILE (its compiled-in default CA path is absent on Android), so
// pass the CA bundle explicitly via CAInfo (see http/curl_transport.h).
CurlTransport transport(http::MakeCurlTransportOptions());
#endif
Request request(HttpMethod::Get, Url(url));
request.SetHeader("User-Agent", user_agent);
Expand Down
Loading