Skip to content

Commit

Permalink
refactor to http proxy builder
Browse files Browse the repository at this point in the history
  • Loading branch information
cwaldren-ld committed Nov 22, 2024
1 parent 0b9fc72 commit f13b133
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ typedef struct _LDPersistenceCustomBuilder* LDPersistenceCustomBuilder;
typedef struct _LDClientHttpPropertiesTlsBuilder*
LDClientHttpPropertiesTlsBuilder;

typedef struct _LDClientHttpPropertiesProxyBuilder*
LDClientHttpPropertiesProxyBuilder;

typedef void (*SetFn)(char const* storage_namespace,
char const* key,
char const* data,
Expand Down Expand Up @@ -421,6 +424,26 @@ LDClientConfigBuilder_HttpProperties_Header(LDClientConfigBuilder b,
char const* key,
char const* value);

/**
* Creates a new proxy options builder for the HttpProperties builder.
*
* If not passed into the HttpProperties
* builder, must be manually freed with LDClientHttpPropertiesProxyBuilder_Free.
*
* @return New builder for proxy options.
*/
LD_EXPORT(LDClientHttpPropertiesProxyBuilder)
LDClientHttpPropertiesProxyBuilder_New(void);

/**
* Frees a proxy options builder. Do not call if the builder was consumed by
* the HttpProperties builder.
*
* @param b Builder to free.
*/
LD_EXPORT(void)
LDClientHttpPropertiesProxyBuilder_Free(LDClientHttpPropertiesProxyBuilder b);

/**
* Specifies an HTTP proxy which the client should use to communicate
* with LaunchDarkly.
Expand Down
32 changes: 26 additions & 6 deletions libs/client-sdk/src/bindings/c/builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,18 @@ using namespace launchdarkly::client_side;
#define FROM_CUSTOM_PERSISTENCE_BUILDER(ptr) \
(reinterpret_cast<LDPersistenceCustomBuilder>(ptr))

#define TO_TLS_BUILDER(ptr) (reinterpret_cast<TlsBuilder*>(ptr))
#define TO_TLS_BUILDER(ptr) \
(reinterpret_cast<HttpPropertiesBuilder::TlsBuilder*>(ptr))

#define FROM_TLS_BUILDER(ptr) \
(reinterpret_cast<LDClientHttpPropertiesTlsBuilder>(ptr))

#define TO_PROXY_BUILDER(ptr) \
(reinterpret_cast<HttpPropertiesBuilder::ProxyBuilder*>(ptr))

#define FROM_PROXY_BUILDER(ptr) \
(reinterpret_cast<LDClientHttpPropertiesProxyBuilder>(ptr))

class PersistenceImplementationWrapper : public IPersistence {
public:
explicit PersistenceImplementationWrapper(LDPersistence impl)
Expand Down Expand Up @@ -311,13 +318,26 @@ LDClientConfigBuilder_HttpProperties_Header(LDClientConfigBuilder b,
TO_BUILDER(b)->HttpProperties().Header(key, value);
}

LD_EXPORT(LDClientHttpPropertiesProxyBuilder)
LDClientHttpPropertiesProxyBuilder_New(void) {
return FROM_PROXY_BUILDER(new HttpPropertiesBuilder::ProxyBuilder());
}

LD_EXPORT(void)
LDClientConfigBuilder_HttpProperties_HttpProxy(LDClientConfigBuilder b,
char const* http_proxy) {
LDClientHttpPropertiesProxyBuilder_Free(LDClientHttpPropertiesProxyBuilder b) {
delete TO_PROXY_BUILDER(b);
}

LD_EXPORT(void)
LDClientConfigBuilder_HttpProperties_HttpProxy(
LDClientConfigBuilder b,
LDClientHttpPropertiesProxyBuilder proxy_builder) {
LD_ASSERT_NOT_NULL(b);
LD_ASSERT_NOT_NULL(http_proxy);
LD_ASSERT_NOT_NULL(proxy_builder);

TO_BUILDER(b)->HttpProperties().Proxy(*TO_PROXY_BUILDER(proxy_builder));

TO_BUILDER(b)->HttpProperties().HttpProxy(http_proxy);
LDClientHttpPropertiesProxyBuilder_Free(proxy_builder);
}

LD_EXPORT(void)
Expand Down Expand Up @@ -353,7 +373,7 @@ LDClientHttpPropertiesTlsBuilder_CustomCAFile(

LD_EXPORT(LDClientHttpPropertiesTlsBuilder)
LDClientHttpPropertiesTlsBuilder_New(void) {
return FROM_TLS_BUILDER(new TlsBuilder());
return FROM_TLS_BUILDER(new HttpPropertiesBuilder::TlsBuilder());
}

LD_EXPORT(void)
Expand Down
4 changes: 2 additions & 2 deletions libs/client-sdk/src/data_sources/streaming_data_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ void StreamingDataSource::Start() {
client_builder.custom_ca_file(*ca_file);
}

if (http_config_.HttpProxy()) {
client_builder.http_proxy(*http_config_.HttpProxy());
if (http_config_.Proxy().HttpProxy()) {
client_builder.http_proxy(*http_config_.Proxy().HttpProxy());
}

auto weak_self = weak_from_this();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,48 @@ class TlsBuilder {
enum built::TlsOptions::VerifyMode verify_mode_;
std::optional<std::string> custom_ca_file_;
};

template <typename SDK>
class ProxyBuilder {
public:
ProxyBuilder();

ProxyBuilder(built::ProxyOptions const& proxy);

/**
* NOTE: This method and the associated 'http_proxy' environment variable
* are only available for the client-side SDK.
*
* Specifies an HTTP proxy which the SDK should use to communicate
* with LaunchDarkly.
*
* SDK <-- HTTP, plaintext --> Proxy <-- HTTPS --> LaunchDarkly
*
* This setting affects streaming mode, polling mode, and event delivery.
* The argument should be of the form: 'http://proxy.example.com:8080'.
*
* The scheme must be 'http' and the port is optional (80 if not
* specified.)
*
* The SDK respects the 'http_proxy' environment variable as an alternative
* to this method. If both are set, this method takes precedence.
*
* @param http_proxy HTTP proxy URL.
*/
template <typename T = SDK,
std::enable_if_t<std::is_same_v<T, ClientSDK>, int> = 0>
ProxyBuilder& HttpProxy(std::string http_proxy) {
http_proxy_ = std::move(http_proxy);
return *this;
}

[[nodiscard]] built::ProxyOptions Build() const;

private:
std::optional<std::string> http_proxy_;
std::optional<std::string> https_proxy_;
};

/**
* Class used for building a set of HttpProperties.
* @tparam SDK The SDK type to build properties for. This affects the default
Expand All @@ -74,6 +116,9 @@ class TlsBuilder {
template <typename SDK>
class HttpPropertiesBuilder {
public:
using TlsBuilder = TlsBuilder<SDK>;
using ProxyBuilder = ProxyBuilder<SDK>;

/**
* Construct a new HttpPropertiesBuilder. The builder will use the default
* properties based on the SDK type. Setting a property will override
Expand Down Expand Up @@ -177,34 +222,14 @@ class HttpPropertiesBuilder {
* @param builder The TLS property builder.
* @return A reference to this builder.
*/
HttpPropertiesBuilder& Tls(TlsBuilder<SDK> builder);
HttpPropertiesBuilder& Tls(TlsBuilder builder);

/**
* NOTE: This method and the associated 'http_proxy' environment variable
* are only available for the client-side SDK.
*
* Specifies an HTTP proxy which the SDK should use to communicate
* with LaunchDarkly.
*
* SDK <-- HTTP, plaintext --> Proxy <-- HTTPS --> LaunchDarkly
*
* This setting affects streaming mode, polling mode, and event delivery.
* The argument should be of the form: 'http://proxy.example.com:8080'.
*
* The scheme must be 'http' and the port is optional (80 if not
* specified.)
*
* The SDK respects the 'http_proxy' environment variable as an alternative
* to this method. If both are set, this method takes precedence.
*
* @param http_proxy HTTP proxy URL.
* @param builder Sets the builder for proxy properties.
* @return A reference to this builder.
*/
template <typename T = SDK,
std::enable_if_t<std::is_same_v<T, ClientSDK>, int> = 0>
HttpPropertiesBuilder& HttpProxy(std::string http_proxy) {
http_proxy_ = std::move(http_proxy);
return *this;
}
HttpPropertiesBuilder& Proxy(ProxyBuilder builder);

[[nodiscard]] built::HttpProperties Build() const;

Expand All @@ -216,8 +241,8 @@ class HttpPropertiesBuilder {
std::string wrapper_name_;
std::string wrapper_version_;
std::map<std::string, std::string> base_headers_;
TlsBuilder<SDK> tls_;
std::optional<std::string> http_proxy_;
TlsBuilder tls_;
ProxyBuilder proxy_;
};

} // namespace launchdarkly::config::shared::builders
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ class TlsOptions final {
std::optional<std::string> ca_bundle_path_;
};

class ProxyOptions final {
public:
ProxyOptions(std::optional<std::string> http_proxy,
std::optional<std::string> https_proxy);

ProxyOptions() = default;
[[nodiscard]] std::optional<std::string> HttpProxy() const;
[[nodiscard]] std::optional<std::string> HttpsProxy() const;

private:
std::optional<std::string> http_proxy_;
std::optional<std::string> https_proxy_;
};

class HttpProperties final {
public:
HttpProperties(std::chrono::milliseconds connect_timeout,
Expand All @@ -31,7 +45,7 @@ class HttpProperties final {
std::chrono::milliseconds response_timeout,
std::map<std::string, std::string> base_headers,
TlsOptions tls,
std::optional<std::string> http_proxy);
ProxyOptions proxy);

[[nodiscard]] std::chrono::milliseconds ConnectTimeout() const;
[[nodiscard]] std::chrono::milliseconds ReadTimeout() const;
Expand All @@ -42,7 +56,7 @@ class HttpProperties final {

[[nodiscard]] TlsOptions const& Tls() const;

[[nodiscard]] std::optional<std::string> HttpProxy() const;
[[nodiscard]] ProxyOptions const& Proxy() const;

private:
std::chrono::milliseconds connect_timeout_;
Expand All @@ -51,10 +65,11 @@ class HttpProperties final {
std::chrono::milliseconds response_timeout_;
std::map<std::string, std::string> base_headers_;
TlsOptions tls_;
std::optional<std::string> http_proxy_;
ProxyOptions proxy_;
};

bool operator==(HttpProperties const& lhs, HttpProperties const& rhs);
bool operator==(ProxyOptions const& lhs, ProxyOptions const& rhs);
bool operator==(TlsOptions const& lhs, TlsOptions const& rhs);

} // namespace launchdarkly::config::shared::built
8 changes: 6 additions & 2 deletions libs/common/include/launchdarkly/config/shared/defaults.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ struct Defaults<ClientSDK> {

static auto TLS() -> shared::built::TlsOptions { return {}; }

static auto NoProxy() -> built::ProxyOptions { return {}; }

static auto HttpProperties() -> shared::built::HttpProperties {
return {std::chrono::seconds{10},
std::chrono::seconds{10},
std::chrono::seconds{10},
std::chrono::seconds{10},
std::map<std::string, std::string>(),
TLS(),
std::nullopt};
NoProxy()};
}

static auto StreamingConfig() -> shared::built::StreamingConfig<ClientSDK> {
Expand Down Expand Up @@ -100,14 +102,16 @@ struct Defaults<ServerSDK> {

static auto TLS() -> shared::built::TlsOptions { return {}; }

static auto NoProxy() -> built::ProxyOptions { return {}; }

static auto HttpProperties() -> built::HttpProperties {
return {std::chrono::seconds{10},
std::chrono::seconds{10},
std::chrono::seconds{10},
std::chrono::seconds{10},
std::map<std::string, std::string>(),
TLS(),
std::nullopt};
NoProxy()};
}

static auto StreamingConfig() -> built::StreamingConfig<ServerSDK> {
Expand Down
28 changes: 23 additions & 5 deletions libs/common/src/config/http_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,33 @@ std::optional<std::string> const& TlsOptions::CustomCAFile() const {
return ca_bundle_path_;
}

ProxyOptions::ProxyOptions(std::optional<std::string> http_proxy,
std::optional<std::string> https_proxy)
: http_proxy_(std::move(http_proxy)),
https_proxy_(std::move(https_proxy)) {}

std::optional<std::string> ProxyOptions::HttpProxy() const {
return http_proxy_;
}

std::optional<std::string> ProxyOptions::HttpsProxy() const {
return https_proxy_;
}

HttpProperties::HttpProperties(std::chrono::milliseconds connect_timeout,
std::chrono::milliseconds read_timeout,
std::chrono::milliseconds write_timeout,
std::chrono::milliseconds response_timeout,
std::map<std::string, std::string> base_headers,
TlsOptions tls,
std::optional<std::string> http_proxy)
ProxyOptions proxy)
: connect_timeout_(connect_timeout),
read_timeout_(read_timeout),
write_timeout_(write_timeout),
response_timeout_(response_timeout),
base_headers_(std::move(base_headers)),
tls_(std::move(tls)),
http_proxy_(std::move(http_proxy)) {}
proxy_(std::move(proxy)) {}

std::chrono::milliseconds HttpProperties::ConnectTimeout() const {
return connect_timeout_;
Expand All @@ -60,21 +73,26 @@ TlsOptions const& HttpProperties::Tls() const {
return tls_;
}

std::optional<std::string> HttpProperties::HttpProxy() const {
return http_proxy_;
ProxyOptions const& HttpProperties::Proxy() const {
return proxy_;
}

bool operator==(HttpProperties const& lhs, HttpProperties const& rhs) {
return lhs.ReadTimeout() == rhs.ReadTimeout() &&
lhs.WriteTimeout() == rhs.WriteTimeout() &&
lhs.ConnectTimeout() == rhs.ConnectTimeout() &&
lhs.BaseHeaders() == rhs.BaseHeaders() && lhs.Tls() == rhs.Tls() &&
lhs.HttpProxy() == rhs.HttpProxy();
lhs.Proxy() == rhs.Proxy();
}

bool operator==(TlsOptions const& lhs, TlsOptions const& rhs) {
return lhs.PeerVerifyMode() == rhs.PeerVerifyMode() &&
lhs.CustomCAFile() == rhs.CustomCAFile();
}

bool operator==(ProxyOptions const& lhs, ProxyOptions const& rhs) {
return lhs.HttpProxy() == rhs.HttpProxy() &&
lhs.HttpsProxy() == rhs.HttpsProxy();
}

} // namespace launchdarkly::config::shared::built
Loading

0 comments on commit f13b133

Please sign in to comment.