From 029f3276dfda8304d7aa84e8968d912d21844a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ulises=20Ni=C3=B1o=20Rivera?= Date: Sun, 6 Mar 2022 18:40:41 -0800 Subject: [PATCH 1/7] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Ulises Niño Rivera --- library/common/config/config.cc | 47 ++++++++++++++++++++++++--------- library/common/http/client.cc | 46 -------------------------------- library/common/http/client.h | 1 - 3 files changed, 35 insertions(+), 59 deletions(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 4cfcae3b10..96fb079305 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 [] - &metadata {} - &stats_domain 127.0.0.1 - &stats_flush_interval 60s @@ -214,18 +215,48 @@ 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 + 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: + headers: + - name: ":scheme" + value: http + request_headers_to_remove: + - x-forwarded-proto + route: + cluster: base + 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 route: - cluster_header: x-envoy-mobile-cluster + cluster: base timeout: 0s retry_policy: per_try_idle_timeout: *per_try_idle_timeout @@ -321,7 +352,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: *base_protocol_options - name: base_clear connect_timeout: *connect_timeout lb_policy: CLUSTER_PROVIDED @@ -350,14 +381,6 @@ R"( 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 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_; From 7fdcea6334e9f166515fe4beddae96f43ccaaf40 Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 19:52:06 -0800 Subject: [PATCH 2/7] mostly done. missing obj-c string joiner Signed-off-by: Jose Nino --- library/common/config/config.cc | 8 +++++--- .../engine/EnvoyConfiguration.java | 14 ++++++++++++++ .../envoyproxy/envoymobile/EngineBuilder.kt | 15 +++++++++++++++ library/objective-c/EnvoyConfiguration.m | 15 +++++++++++++++ library/objective-c/EnvoyEngine.h | 2 ++ library/swift/EngineBuilder.swift | 14 ++++++++++++++ .../engine/EnvoyConfigurationTest.kt | 11 +++++++---- .../envoymobile/EngineBuilderTest.kt | 10 ++++++++++ test/swift/EngineBuilderTests.swift | 19 +++++++++++++++++++ 9 files changed, 101 insertions(+), 7 deletions(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 96fb079305..6bdde07d2d 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -46,7 +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 [] +- &h2_hostnames ["api.foo.bar"] - &metadata {} - &stats_domain 127.0.0.1 - &stats_flush_interval 60s @@ -239,13 +239,15 @@ const char* config_template = R"( routes: #{custom_routes} - match: + prefix: "/" headers: - name: ":scheme" - value: http + string_match: + exact: http request_headers_to_remove: - x-forwarded-proto route: - cluster: base + cluster: base_clear timeout: 0s retry_policy: per_try_idle_timeout: *per_try_idle_timeout 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..4b07572e3f 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,18 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { appendString:[[NSString alloc] initWithUTF8String:route_cache_reset_filter_insert]]; } + BOOL hasH2Hostnames = self.h2Hostnames.count > 0; + if (hasH2Hostnames) { + templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{fake_remote_responses}" + withString:self.directResponses]; + [customClusters appendString:[[NSString alloc] initWithUTF8String:fake_remote_cluster_insert]]; + [customListeners + appendString:[[NSString alloc] initWithUTF8String:fake_remote_listener_insert]]; + [customRoutes appendString:self.directResponseMatchers]; + [customFilters + appendString:[[NSString alloc] initWithUTF8String:route_cache_reset_filter_insert]]; + } + templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{custom_clusters}" withString:customClusters]; templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{custom_listeners}" @@ -138,6 +152,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 ? @"[]" : @"[]"]; [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/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, From ec39d58b593bae7f10f65b2997cc5854d36d402c Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 19:58:06 -0800 Subject: [PATCH 3/7] move to h2 Signed-off-by: Jose Nino --- library/common/config/config.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 6bdde07d2d..3311ad84a6 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -90,6 +90,18 @@ const std::string config_header = R"( auto_sni: true auto_san_validation: true +!ignore protocol_defs: &http2_protocol_options_defs + 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: @@ -115,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: @@ -354,7 +366,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: *base_protocol_options + typed_extension_protocol_options: *alpn_protocol_options - name: base_clear connect_timeout: *connect_timeout lb_policy: CLUSTER_PROVIDED @@ -382,7 +394,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 + typed_extension_protocol_options: *http2_protocol_options_defs stats_flush_interval: *stats_flush_interval stats_sinks: *stats_sinks stats_config: From 607c72f6502f4ec585a3d486e8472fa495d04761 Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 20:00:10 -0800 Subject: [PATCH 4/7] names Signed-off-by: Jose Nino --- library/common/config/config.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 3311ad84a6..2509a07382 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -76,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: @@ -90,7 +90,7 @@ const std::string config_header = R"( auto_sni: true auto_san_validation: true -!ignore protocol_defs: &http2_protocol_options_defs +!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: @@ -374,7 +374,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 @@ -394,7 +394,7 @@ R"( trust_chain_verification: *trust_chain_verification upstream_connection_options: *upstream_opts circuit_breakers: *circuit_breakers_settings - typed_extension_protocol_options: *http2_protocol_options_defs + typed_extension_protocol_options: *http2_protocol_options stats_flush_interval: *stats_flush_interval stats_sinks: *stats_sinks stats_config: From 9e2b3553cc12859edd2f7d3f59bd051e121d97e3 Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 20:30:19 -0800 Subject: [PATCH 5/7] more red Signed-off-by: Jose Nino --- library/common/config/config.cc | 1 - test/common/engine_test.cc | 1 - test/common/http/client_test.cc | 3 --- test/common/main_interface_test.cc | 1 - 4 files changed, 6 deletions(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 2509a07382..76428dea24 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -167,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: 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: From 4b71d555bc320784a9172e1164595df3d0d5083e Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 22:49:08 -0800 Subject: [PATCH 6/7] more Signed-off-by: Jose Nino --- library/common/config/config.cc | 3 +++ library/objective-c/EnvoyConfiguration.m | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/library/common/config/config.cc b/library/common/config/config.cc index 76428dea24..91c8c1cb45 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -235,6 +235,7 @@ const char* config_template = R"( - match: { prefix: "/" } request_headers_to_remove: - x-forwarded-proto + - x-envoy-mobile-upstream-protocol route: cluster: base_h2 timeout: 0s @@ -257,6 +258,7 @@ const char* config_template = R"( exact: http request_headers_to_remove: - x-forwarded-proto + - x-envoy-mobile-upstream-protocol route: cluster: base_clear timeout: 0s @@ -268,6 +270,7 @@ const char* config_template = R"( - match: { prefix: "/" } request_headers_to_remove: - x-forwarded-proto + - x-envoy-mobile-upstream-protocol route: cluster: base timeout: 0s diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index 4b07572e3f..00ff497896 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -152,7 +152,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 ? @"[]" : @"[]"]; + [definitions appendFormat:@"- &h2_hostnames %@\n", hasH2Hostnames ? @"[\"host.name\"]" : @"[\"host.name\"]"]; [definitions appendFormat:@"- &stream_idle_timeout %lus\n", (unsigned long)self.streamIdleTimeoutSeconds]; [definitions From 7602a04f6c8d5301490e391bb5b8757f9a2c4b5f Mon Sep 17 00:00:00 2001 From: Jose Nino Date: Sun, 6 Mar 2022 22:50:49 -0800 Subject: [PATCH 7/7] reminder Signed-off-by: Jose Nino --- library/objective-c/EnvoyConfiguration.m | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index 00ff497896..868bb6fc02 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -104,14 +104,7 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { BOOL hasH2Hostnames = self.h2Hostnames.count > 0; if (hasH2Hostnames) { - templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{fake_remote_responses}" - withString:self.directResponses]; - [customClusters appendString:[[NSString alloc] initWithUTF8String:fake_remote_cluster_insert]]; - [customListeners - appendString:[[NSString alloc] initWithUTF8String:fake_remote_listener_insert]]; - [customRoutes appendString:self.directResponseMatchers]; - [customFilters - appendString:[[NSString alloc] initWithUTF8String:route_cache_reset_filter_insert]]; + // FIXME: build string. } templateYAML = [templateYAML stringByReplacingOccurrencesOfString:@"#{custom_clusters}"