diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 4cfcae3b10..91c8c1cb45 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -46,6 +46,7 @@ const std::string config_header = R"( - &enable_interface_binding false - &h2_connection_keepalive_idle_interval 100000s - &h2_connection_keepalive_timeout 10s +- &h2_hostnames ["api.foo.bar"] - &metadata {} - &stats_domain 127.0.0.1 - &stats_flush_interval 60s @@ -75,7 +76,7 @@ const std::string config_header = R"( address: socket_address: { address: *statsd_host, port_value: *statsd_port } -!ignore protocol_defs: &http1_protocol_options_defs +!ignore http1_protocol_options_defs: &http1_protocol_options envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: @@ -89,6 +90,18 @@ const std::string config_header = R"( auto_sni: true auto_san_validation: true +!ignore http2_protocol_options_defs: &http2_protocol_options + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: + connection_keepalive: + connection_idle_interval: *h2_connection_keepalive_idle_interval + timeout: *h2_connection_keepalive_timeout + upstream_http_protocol_options: + auto_sni: true + auto_san_validation: true + !ignore admin_interface_defs: &admin_interface address: socket_address: @@ -114,7 +127,7 @@ R"( )"; const char* config_template = R"( -!ignore base_protocol_options_defs: &base_protocol_options +!ignore alpn_protocol_options_defs: &alpn_protocol_options envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions auto_config: @@ -154,7 +167,6 @@ const char* config_template = R"( direct_response: { status: 404, body: { inline_string: "not found" } } request_headers_to_remove: - x-forwarded-proto - - x-envoy-mobile-cluster http_filters: - name: envoy.router typed_config: @@ -214,18 +226,53 @@ const char* config_template = R"( route_config: name: api_router virtual_hosts: - - name: api + - name: h2 + include_attempt_count_in_response: true + virtual_clusters: *virtual_clusters + domains: *h2_hostnames + routes: +#{custom_routes} + - match: { prefix: "/" } + request_headers_to_remove: + - x-forwarded-proto + - x-envoy-mobile-upstream-protocol + route: + cluster: base_h2 + timeout: 0s + retry_policy: + per_try_idle_timeout: *per_try_idle_timeout + retry_back_off: + base_interval: 0.25s + max_interval: 60s + - name: catchall include_attempt_count_in_response: true virtual_clusters: *virtual_clusters domains: ["*"] routes: #{custom_routes} + - match: + prefix: "/" + headers: + - name: ":scheme" + string_match: + exact: http + request_headers_to_remove: + - x-forwarded-proto + - x-envoy-mobile-upstream-protocol + route: + cluster: base_clear + timeout: 0s + retry_policy: + per_try_idle_timeout: *per_try_idle_timeout + retry_back_off: + base_interval: 0.25s + max_interval: 60s - match: { prefix: "/" } request_headers_to_remove: - x-forwarded-proto - - x-envoy-mobile-cluster + - x-envoy-mobile-upstream-protocol route: - cluster_header: x-envoy-mobile-cluster + cluster: base timeout: 0s retry_policy: per_try_idle_timeout: *per_try_idle_timeout @@ -321,7 +368,7 @@ R"( // Therefore, the ejection time is short and the interval for unejection is tight, but not too // tight to cause unnecessary churn. R"( - typed_extension_protocol_options: *http1_protocol_options_defs + typed_extension_protocol_options: *alpn_protocol_options - name: base_clear connect_timeout: *connect_timeout lb_policy: CLUSTER_PROVIDED @@ -329,7 +376,7 @@ R"( transport_socket: { name: envoy.transport_sockets.raw_buffer } upstream_connection_options: *upstream_opts circuit_breakers: *circuit_breakers_settings - typed_extension_protocol_options: *http1_protocol_options_defs + typed_extension_protocol_options: *http1_protocol_options - name: base_h2 http2_protocol_options: {} connect_timeout: *connect_timeout @@ -349,15 +396,7 @@ R"( trust_chain_verification: *trust_chain_verification upstream_connection_options: *upstream_opts circuit_breakers: *circuit_breakers_settings - typed_extension_protocol_options: *base_protocol_options - - name: base_alpn - connect_timeout: *connect_timeout - lb_policy: CLUSTER_PROVIDED - cluster_type: *base_cluster_type - transport_socket: *base_tls_socket - upstream_connection_options: *upstream_opts - circuit_breakers: *circuit_breakers_settings - typed_extension_protocol_options: *base_protocol_options + typed_extension_protocol_options: *http2_protocol_options stats_flush_interval: *stats_flush_interval stats_sinks: *stats_sinks stats_config: diff --git a/library/common/http/client.cc b/library/common/http/client.cc index e44da6631c..1891c3104d 100644 --- a/library/common/http/client.cc +++ b/library/common/http/client.cc @@ -414,7 +414,6 @@ void Client::sendHeaders(envoy_stream_t stream, envoy_headers headers, bool end_ if (direct_stream) { ScopeTrackerScopeState scope(direct_stream.get(), scopeTracker()); RequestHeaderMapPtr internal_headers = Utility::toRequestHeaders(headers); - setDestinationCluster(*internal_headers); // Set the x-forwarded-proto header to https because Envoy Mobile only has clusters with TLS // enabled. This is done here because the ApiListener's synthetic connection would make the // Http::ConnectionManager set the scheme to http otherwise. In the future we might want to @@ -585,53 +584,8 @@ void Client::removeStream(envoy_stream_t stream_handle) { } namespace { - -const LowerCaseString ClusterHeader{"x-envoy-mobile-cluster"}; const LowerCaseString H2UpstreamHeader{"x-envoy-mobile-upstream-protocol"}; - -// Alternate clusters included here are a stopgap to make it less likely for a given connection -// class to suffer "catastrophic" failure of all outbound requests due to a network blip, by -// distributing requests across a minimum of two potential connections per connection class. -// Long-term we will be working to generally provide more responsive connection handling within -// Envoy itself. - -const char* BaseCluster = "base"; -const char* H2Cluster = "base_h2"; -const char* ClearTextCluster = "base_clear"; -const char* AlpnCluster = "base_alpn"; - } // namespace -void Client::setDestinationCluster(Http::RequestHeaderMap& headers) { - // Determine upstream cluster: - // - Use TLS by default. - // - Use http/2 or ALPN if requested explicitly via x-envoy-mobile-upstream-protocol. - // - Force http/1.1 if request scheme is http (cleartext). - const char* cluster{}; - auto h2_header = headers.get(H2UpstreamHeader); - if (headers.getSchemeValue() == Headers::get().SchemeValues.Http) { - cluster = ClearTextCluster; - } else if (!h2_header.empty()) { - ASSERT(h2_header.size() == 1); - const auto value = h2_header[0]->value().getStringView(); - if (value == "http2") { - cluster = H2Cluster; - } else if (value == "alpn") { - cluster = AlpnCluster; - } else { - RELEASE_ASSERT(value == "http1", fmt::format("using unsupported protocol version {}", value)); - cluster = BaseCluster; - } - } else { - cluster = BaseCluster; - } - - if (!h2_header.empty()) { - headers.remove(H2UpstreamHeader); - } - - headers.addCopy(ClusterHeader, std::string{cluster}); -} - } // namespace Http } // namespace Envoy diff --git a/library/common/http/client.h b/library/common/http/client.h index e66c065628..3182ea4837 100644 --- a/library/common/http/client.h +++ b/library/common/http/client.h @@ -317,7 +317,6 @@ class Client : public Logger::Loggable { }; DirectStreamSharedPtr getStream(envoy_stream_t stream_handle, GetStreamFilters filters); void removeStream(envoy_stream_t stream_handle); - void setDestinationCluster(RequestHeaderMap& headers); ApiListener& api_listener_; Event::ProvisionalDispatcher& dispatcher_; diff --git a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java index e990835bcc..77c07a010e 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java +++ b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java @@ -38,6 +38,7 @@ public enum TrustChainVerification { public final Boolean enableInterfaceBinding; public final Integer h2ConnectionKeepaliveIdleIntervalMilliseconds; public final Integer h2ConnectionKeepaliveTimeoutSeconds; + public final List h2Hostnames; public final List httpPlatformFilterFactories; public final Integer statsFlushSeconds; public final Integer streamIdleTimeoutSeconds; @@ -70,6 +71,7 @@ public enum TrustChainVerification { * @param h2ConnectionKeepaliveIdleIntervalMilliseconds rate in milliseconds seconds to send h2 * pings on stream creation. * @param h2ConnectionKeepaliveTimeoutSeconds rate in seconds to timeout h2 pings. + * @param h2Hostnames hostnames to force h2 connections for. * @param statsFlushSeconds interval at which to flush Envoy stats. * @param streamIdleTimeoutSeconds idle timeout for HTTP streams. * @param perTryIdleTimeoutSeconds per try idle timeout for HTTP streams. @@ -88,6 +90,7 @@ public EnvoyConfiguration( List dnsFallbackNameservers, Boolean dnsFilterUnroutableFamilies, boolean enableHappyEyeballs, boolean enableInterfaceBinding, int h2ConnectionKeepaliveIdleIntervalMilliseconds, int h2ConnectionKeepaliveTimeoutSeconds, + List h2Hostnames, int statsFlushSeconds, int streamIdleTimeoutSeconds, int perTryIdleTimeoutSeconds, String appVersion, String appId, TrustChainVerification trustChainVerification, String virtualClusters, List nativeFilterChain, @@ -109,6 +112,7 @@ public EnvoyConfiguration( this.h2ConnectionKeepaliveIdleIntervalMilliseconds = h2ConnectionKeepaliveIdleIntervalMilliseconds; this.h2ConnectionKeepaliveTimeoutSeconds = h2ConnectionKeepaliveTimeoutSeconds; + this.h2Hostnames = h2Hostnames; this.statsFlushSeconds = statsFlushSeconds; this.streamIdleTimeoutSeconds = streamIdleTimeoutSeconds; this.perTryIdleTimeoutSeconds = perTryIdleTimeoutSeconds; @@ -161,6 +165,15 @@ String resolveTemplate(final String templateYAML, final String platformFilterTem dnsFallbackNameserversAsString = sj.toString(); } + String h2HostnamesAsString = "[]"; + if (!h2Hostnames.isEmpty()) { + StringJoiner sj = new StringJoiner(",", "[", "]"); + for (String hostname : h2Hostnames) { + sj.add(String.format("\"%s\"", hostname)); + } + h2HostnamesAsString = sj.toString(); + } + String dnsResolverConfig = String.format( "{\"@type\":\"type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig\",\"resolvers\":%s,\"use_resolvers_as_fallback\": %s, \"filter_unroutable_families\": %s}", dnsFallbackNameserversAsString, !dnsFallbackNameservers.isEmpty() ? "true" : "false", @@ -185,6 +198,7 @@ String resolveTemplate(final String templateYAML, final String platformFilterTem h2ConnectionKeepaliveIdleIntervalMilliseconds / 1000.0)) .append(String.format("- &h2_connection_keepalive_timeout %ss\n", h2ConnectionKeepaliveTimeoutSeconds)) + .append(String.format("- &h2_hostnames %s\n", h2HostnamesAsString)) .append(String.format("- &stream_idle_timeout %ss\n", streamIdleTimeoutSeconds)) .append(String.format("- &per_try_idle_timeout %ss\n", perTryIdleTimeoutSeconds)) .append(String.format("- &metadata { device_os: %s, app_version: %s, app_id: %s }\n", diff --git a/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt b/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt index 44614116c1..524f1ec3d1 100644 --- a/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt +++ b/library/kotlin/io/envoyproxy/envoymobile/EngineBuilder.kt @@ -42,6 +42,7 @@ open class EngineBuilder( private var enableInterfaceBinding = false private var h2ConnectionKeepaliveIdleIntervalMilliseconds = 100000000 private var h2ConnectionKeepaliveTimeoutSeconds = 10 + private var h2Hostnames = listOf() private var statsFlushSeconds = 60 private var streamIdleTimeoutSeconds = 15 private var perTryIdleTimeoutSeconds = 15 @@ -231,6 +232,18 @@ open class EngineBuilder( return this } + /** + * Add a list of hostnames to force h2 connections for. + * + * @param h2Hostnames addresses to use. + * + * @return this builder. + */ + fun addDNSFallbackNameservers(h2Hostnames: List): EngineBuilder { + this.h2Hostnames = h2Hostnames + return this + } + /** * Add an interval at which to flush Envoy stats. * @@ -442,6 +455,7 @@ open class EngineBuilder( enableInterfaceBinding, h2ConnectionKeepaliveIdleIntervalMilliseconds, h2ConnectionKeepaliveTimeoutSeconds, + h2Hostnames, statsFlushSeconds, streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds, @@ -476,6 +490,7 @@ open class EngineBuilder( enableInterfaceBinding, h2ConnectionKeepaliveIdleIntervalMilliseconds, h2ConnectionKeepaliveTimeoutSeconds, + h2Hostnames, statsFlushSeconds, streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds, diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index 7b718f2884..868bb6fc02 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -17,6 +17,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds h2ConnectionKeepaliveTimeoutSeconds:(UInt32)h2ConnectionKeepaliveTimeoutSeconds + h2Hostnames:(NSArray *)h2Hostnames statsFlushSeconds:(UInt32)statsFlushSeconds streamIdleTimeoutSeconds:(UInt32)streamIdleTimeoutSeconds perTryIdleTimeoutSeconds:(UInt32)perTryIdleTimeoutSeconds @@ -50,6 +51,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled self.h2ConnectionKeepaliveIdleIntervalMilliseconds = h2ConnectionKeepaliveIdleIntervalMilliseconds; self.h2ConnectionKeepaliveTimeoutSeconds = h2ConnectionKeepaliveTimeoutSeconds; + self.h2Hostnames = h2Hostnames; self.statsFlushSeconds = statsFlushSeconds; self.streamIdleTimeoutSeconds = streamIdleTimeoutSeconds; self.perTryIdleTimeoutSeconds = perTryIdleTimeoutSeconds; @@ -100,6 +102,11 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { appendString:[[NSString alloc] initWithUTF8String:route_cache_reset_filter_insert]]; } + BOOL hasH2Hostnames = self.h2Hostnames.count > 0; + if (hasH2Hostnames) { + // FIXME: build string. + } + templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{custom_clusters}" withString:customClusters]; templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{custom_listeners}" @@ -138,6 +145,7 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { (double)self.h2ConnectionKeepaliveIdleIntervalMilliseconds / 1000.0]; [definitions appendFormat:@"- &h2_connection_keepalive_timeout %lus\n", (unsigned long)self.h2ConnectionKeepaliveTimeoutSeconds]; + [definitions appendFormat:@"- &h2_hostnames %@\n", hasH2Hostnames ? @"[\"host.name\"]" : @"[\"host.name\"]"]; [definitions appendFormat:@"- &stream_idle_timeout %lus\n", (unsigned long)self.streamIdleTimeoutSeconds]; [definitions diff --git a/library/objective-c/EnvoyEngine.h b/library/objective-c/EnvoyEngine.h index cd60ba8a83..d66217cb48 100644 --- a/library/objective-c/EnvoyEngine.h +++ b/library/objective-c/EnvoyEngine.h @@ -341,6 +341,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; @property (nonatomic, assign) BOOL enableInterfaceBinding; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveIdleIntervalMilliseconds; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveTimeoutSeconds; +@property (nonatomic, strong) NSArray *h2Hostnames; @property (nonatomic, assign) UInt32 statsFlushSeconds; @property (nonatomic, assign) UInt32 streamIdleTimeoutSeconds; @property (nonatomic, assign) UInt32 perTryIdleTimeoutSeconds; @@ -369,6 +370,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds h2ConnectionKeepaliveTimeoutSeconds:(UInt32)h2ConnectionKeepaliveTimeoutSeconds + h2Hostnames:(NSArray *)h2Hostnames statsFlushSeconds:(UInt32)statsFlushSeconds streamIdleTimeoutSeconds:(UInt32)streamIdleTimeoutSeconds perTryIdleTimeoutSeconds:(UInt32)perTryIdleTimeoutSeconds diff --git a/library/swift/EngineBuilder.swift b/library/swift/EngineBuilder.swift index 6c750b7068..6188700b82 100644 --- a/library/swift/EngineBuilder.swift +++ b/library/swift/EngineBuilder.swift @@ -25,6 +25,7 @@ open class EngineBuilder: NSObject { private var enableInterfaceBinding: Bool = false private var h2ConnectionKeepaliveIdleIntervalMilliseconds: UInt32 = 100000000 private var h2ConnectionKeepaliveTimeoutSeconds: UInt32 = 10 + private var h2Hostnames: [String] = [] private var statsFlushSeconds: UInt32 = 60 private var streamIdleTimeoutSeconds: UInt32 = 15 private var perTryIdleTimeoutSeconds: UInt32 = 15 @@ -185,6 +186,18 @@ open class EngineBuilder: NSObject { return self } + /// Add a list of hostnames to force h2 connections for. + /// + /// - parameter h2Hostnames: Hostnames to use. + /// + /// - returns: This builder. + @discardableResult + public func addH2Hostnames( + _ h2Hostnames: [String]) -> Self { + self.h2Hostnames = h2Hostnames + return self + } + /// Add an interval at which to flush Envoy stats. /// /// - parameter statsFlushSeconds: Interval at which to flush Envoy stats. @@ -381,6 +394,7 @@ open class EngineBuilder: NSObject { h2ConnectionKeepaliveIdleIntervalMilliseconds: self.h2ConnectionKeepaliveIdleIntervalMilliseconds, h2ConnectionKeepaliveTimeoutSeconds: self.h2ConnectionKeepaliveTimeoutSeconds, + h2Hostnames: self.h2Hostnames, statsFlushSeconds: self.statsFlushSeconds, streamIdleTimeoutSeconds: self.streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds: self.perTryIdleTimeoutSeconds, diff --git a/test/common/engine_test.cc b/test/common/engine_test.cc index a1294d1414..15f7f529df 100644 --- a/test/common/engine_test.cc +++ b/test/common/engine_test.cc @@ -28,7 +28,6 @@ const std::string MINIMAL_TEST_CONFIG = R"( routes: - match: { prefix: "/" } route: - cluster_header: x-envoy-mobile-cluster retry_policy: retry_back_off: { base_interval: 0.25s, max_interval: 60s } http_filters: diff --git a/test/common/http/client_test.cc b/test/common/http/client_test.cc index 21c9a5b099..46a227920e 100644 --- a/test/common/http/client_test.cc +++ b/test/common/http/client_test.cc @@ -177,7 +177,6 @@ TEST_P(ClientTest, SetDestinationClusterUpstreamProtocol) { {":method", "GET"}, {":authority", "host"}, {":path", "/"}, - {"x-envoy-mobile-cluster", "base_h2"}, {"x-forwarded-proto", "https"}, }; EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -196,7 +195,6 @@ TEST_P(ClientTest, SetDestinationClusterUpstreamProtocol) { {":method", "GET"}, {":authority", "host"}, {":path", "/"}, - {"x-envoy-mobile-cluster", "base_alpn"}, {"x-forwarded-proto", "https"}, }; EXPECT_CALL(dispatcher_, pushTrackedObject(_)); @@ -215,7 +213,6 @@ TEST_P(ClientTest, SetDestinationClusterUpstreamProtocol) { {":method", "GET"}, {":authority", "host"}, {":path", "/"}, - {"x-envoy-mobile-cluster", "base"}, {"x-forwarded-proto", "https"}, }; EXPECT_CALL(dispatcher_, pushTrackedObject(_)); diff --git a/test/common/main_interface_test.cc b/test/common/main_interface_test.cc index 909b0dfe63..1e439bf687 100644 --- a/test/common/main_interface_test.cc +++ b/test/common/main_interface_test.cc @@ -45,7 +45,6 @@ const std::string MINIMAL_TEST_CONFIG = R"( routes: - match: { prefix: "/" } route: - cluster_header: x-envoy-mobile-cluster retry_policy: retry_back_off: { base_interval: 0.25s, max_interval: 60s } http_filters: diff --git a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt index d872923fd0..ff79bb6cf6 100644 --- a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt +++ b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt @@ -30,7 +30,7 @@ class EnvoyConfigurationTest { fun `resolving with default configuration resolves with values`() { val envoyConfiguration = EnvoyConfiguration( false, "stats.foo.com", null, 123, 234, 345, 456, 321, "[hostname]", listOf("8.8.8.8"), true, - true, true, 222, 333, 567, 678, 910, "v1.2.3", "com.mydomain.myapp", + true, true, 222, 333, listOf("host.name"), 567, 678, 910, "v1.2.3", "com.mydomain.myapp", TrustChainVerification.ACCEPT_UNTRUSTED, "[test]", listOf(EnvoyNativeFilterConfig("filter_name", "test_config")), emptyList(), emptyMap() ) @@ -60,6 +60,9 @@ class EnvoyConfigurationTest { assertThat(resolvedTemplate).contains("&h2_connection_keepalive_idle_interval 0.222s") assertThat(resolvedTemplate).contains("&h2_connection_keepalive_timeout 333s") + // H2 Hostnames + assertThat(resolvedTemplate).contains("&h2_hostnames [\"host.name\"]") + // Metadata assertThat(resolvedTemplate).contains("os: Android") assertThat(resolvedTemplate).contains("app_version: v1.2.3") @@ -87,7 +90,7 @@ class EnvoyConfigurationTest { fun `resolving with alternate values also sets appropriate config`() { val envoyConfiguration = EnvoyConfiguration( false, "stats.foo.com", null, 123, 234, 345, 456, 321, "[hostname]", emptyList(), false, - false, false, 222, 333, 567, 678, 910, "v1.2.3", "com.mydomain.myapp", + false, false, 222, 333, emptyList(), 567, 678, 910, "v1.2.3", "com.mydomain.myapp", TrustChainVerification.ACCEPT_UNTRUSTED, "[test]", listOf(EnvoyNativeFilterConfig("filter_name", "test_config")), emptyList(), emptyMap() ) @@ -109,7 +112,7 @@ class EnvoyConfigurationTest { fun `resolve templates with invalid templates will throw on build`() { val envoyConfiguration = EnvoyConfiguration( false, "stats.foo.com", null, 123, 234, 345, 456, 321, "[hostname]", emptyList(), false, - false, false, 123, 123, 567, 678, 910, "v1.2.3", "com.mydomain.myapp", + false, false, 123, 123, emptyList(), 567, 678, 910, "v1.2.3", "com.mydomain.myapp", TrustChainVerification.ACCEPT_UNTRUSTED, "[test]", emptyList(), emptyList(), emptyMap() ) @@ -125,7 +128,7 @@ class EnvoyConfigurationTest { fun `cannot configure both statsD and gRPC stat sink`() { val envoyConfiguration = EnvoyConfiguration( false, "stats.foo.com", 5050, 123, 234, 345, 456, 321, "[hostname]", emptyList(), false, - false, false, 123, 123, 567, 678, 910, "v1.2.3", "com.mydomain.myapp", + false, false, 123, 123, emptyList(), 567, 678, 910, "v1.2.3", "com.mydomain.myapp", TrustChainVerification.ACCEPT_UNTRUSTED, "[test]", emptyList(), emptyList(), emptyMap() ) diff --git a/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt b/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt index b2670c7eb6..4308910ebf 100644 --- a/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt +++ b/test/kotlin/io/envoyproxy/envoymobile/EngineBuilderTest.kt @@ -140,6 +140,16 @@ class EngineBuilderTest { assertThat(engine.envoyConfiguration!!.h2ConnectionKeepaliveTimeoutSeconds).isEqualTo(1234) } + @Test + fun `specifying h2 hostnames overrides default`() { + engineBuilder = EngineBuilder(Standard()) + engineBuilder.addEngineType { envoyEngine } + engineBuilder.addDNSFallbackNameservers(listOf("api.foo.bar")) + + val engine = engineBuilder.build() as EngineImpl + assertThat(engine.envoyConfiguration!!.h2Hostnames.size).isEqualTo(1) + } + @Test fun `specifying stats flush overrides default`() { engineBuilder = EngineBuilder(Standard()) diff --git a/test/swift/EngineBuilderTests.swift b/test/swift/EngineBuilderTests.swift index 0f85898f98..7707305730 100644 --- a/test/swift/EngineBuilderTests.swift +++ b/test/swift/EngineBuilderTests.swift @@ -223,6 +223,20 @@ final class EngineBuilderTests: XCTestCase { self.waitForExpectations(timeout: 0.01) } + func testAddingH2HostnamesAddsToConfigurationWhenRunningEnvoy() { + let expectation = self.expectation(description: "Run called with expected data") + MockEnvoyEngine.onRunWithConfig = { config, _ in + XCTAssertEqual(1, config.h2Hostnames.count) + expectation.fulfill() + } + + _ = EngineBuilder() + .addEngineType(MockEnvoyEngine.self) + .addH2Hostnames(["host.name"]) + .build() + self.waitForExpectations(timeout: 0.01) + } + func testAddingPlatformFiltersToConfigurationWhenRunningEnvoy() { let expectation = self.expectation(description: "Run called with expected data") MockEnvoyEngine.onRunWithConfig = { config, _ in @@ -363,6 +377,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: true, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, + h2Hostnames: ["host.name"], statsFlushSeconds: 600, streamIdleTimeoutSeconds: 700, perTryIdleTimeoutSeconds: 777, @@ -393,6 +408,8 @@ final class EngineBuilderTests: XCTestCase { XCTAssertTrue(resolvedYAML.contains("&h2_connection_keepalive_idle_interval 0.001s")) XCTAssertTrue(resolvedYAML.contains("&h2_connection_keepalive_timeout 333s")) + XCTAssertTrue(resolvedYAML.contains("&h2_hostnames [\"host.name\"]")) + XCTAssertTrue(resolvedYAML.contains("&stream_idle_timeout 700s")) XCTAssertTrue(resolvedYAML.contains("&per_try_idle_timeout 777s")) @@ -429,6 +446,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: false, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, + h2Hostnames: [], statsFlushSeconds: 600, streamIdleTimeoutSeconds: 700, perTryIdleTimeoutSeconds: 777, @@ -465,6 +483,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: false, h2ConnectionKeepaliveIdleIntervalMilliseconds: 222, h2ConnectionKeepaliveTimeoutSeconds: 333, + h2Hostnames: [], statsFlushSeconds: 600, streamIdleTimeoutSeconds: 700, perTryIdleTimeoutSeconds: 700,