浏览代码

Add helpers for creating transports (#2029)

Motivation:

Creating an HTTP/2 transport requires quite a bit of typing and knowing
what types to use. We can make use of type inference to make this a bit
easier for users.

Modifications:

- Add constrained extensions to `ClientTransport` and `ServerTransport`
allowing for `http2NIO` and `http2NIOTS` transports to be created via
static methods. This makes it possible for transports to be created
inline in the `init` of a `GRPCClient` or `GRPCServer` without the users
need the full type.
- Extend the `defaults` functions so that they can take an optional
trailing closure to further modify the defaults. This allows for configs
to be created and modified inline when making a transport.
- A config is now required to create client transports and the NIOTS
server transport as these will soon require a transport security config.

Results:

Easier to create clients/servers
George Barnett 1 年之前
父节点
当前提交
1699a6fd99

+ 6 - 2
Examples/v2/echo/Subcommands/Collect.swift

@@ -29,8 +29,12 @@ struct Collect: AsyncParsableCommand {
   var arguments: ClientArguments
 
   func run() async throws {
-    let transport = try HTTP2ClientTransport.Posix(target: self.arguments.target)
-    let client = GRPCClient(transport: transport)
+    let client = GRPCClient(
+      transport: try .http2NIOPosix(
+        target: self.arguments.target,
+        config: .defaults()
+      )
+    )
 
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask {

+ 6 - 2
Examples/v2/echo/Subcommands/Expand.swift

@@ -29,8 +29,12 @@ struct Expand: AsyncParsableCommand {
   var arguments: ClientArguments
 
   func run() async throws {
-    let transport = try HTTP2ClientTransport.Posix(target: self.arguments.target)
-    let client = GRPCClient(transport: transport)
+    let client = GRPCClient(
+      transport: try .http2NIOPosix(
+        target: self.arguments.target,
+        config: .defaults()
+      )
+    )
 
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask {

+ 6 - 2
Examples/v2/echo/Subcommands/Get.swift

@@ -27,8 +27,12 @@ struct Get: AsyncParsableCommand {
   var arguments: ClientArguments
 
   func run() async throws {
-    let transport = try HTTP2ClientTransport.Posix(target: self.arguments.target)
-    let client = GRPCClient(transport: transport)
+    let client = GRPCClient(
+      transport: try .http2NIOPosix(
+        target: self.arguments.target,
+        config: .defaults()
+      )
+    )
 
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask {

+ 10 - 6
Examples/v2/echo/Subcommands/Serve.swift

@@ -27,15 +27,19 @@ struct Serve: AsyncParsableCommand {
   var port: Int = 1234
 
   func run() async throws {
-    let transport = HTTP2ServerTransport.Posix(
-      address: .ipv4(host: "127.0.0.1", port: self.port),
-      config: .defaults(transportSecurity: .plaintext)
+    let server = GRPCServer(
+      transport: .http2NIOPosix(
+        address: .ipv4(host: "127.0.0.1", port: self.port),
+        config: .defaults(transportSecurity: .plaintext)
+      ),
+      services: [EchoService()]
     )
-    let server = GRPCServer(transport: transport, services: [EchoService()])
+
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask { try await server.run() }
-      let address = try await transport.listeningAddress
-      print("server listening on \(address)")
+      if let address = try await server.listeningAddress {
+        print("Echo listening on \(address)")
+      }
     }
   }
 }

+ 6 - 2
Examples/v2/echo/Subcommands/Update.swift

@@ -29,8 +29,12 @@ struct Update: AsyncParsableCommand {
   var arguments: ClientArguments
 
   func run() async throws {
-    let transport = try HTTP2ClientTransport.Posix(target: self.arguments.target)
-    let client = GRPCClient(transport: transport)
+    let client = GRPCClient(
+      transport: try .http2NIOPosix(
+        target: self.arguments.target,
+        config: .defaults()
+      )
+    )
 
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask {

+ 6 - 2
Examples/v2/hello-world/Subcommands/Greet.swift

@@ -30,8 +30,12 @@ struct Greet: AsyncParsableCommand {
 
   func run() async throws {
     try await withThrowingDiscardingTaskGroup { group in
-      let http2 = try HTTP2ClientTransport.Posix(target: .ipv4(host: "127.0.0.1", port: self.port))
-      let client = GRPCClient(transport: http2)
+      let client = GRPCClient(
+        transport: try .http2NIOPosix(
+          target: .ipv4(host: "127.0.0.1", port: self.port),
+          config: .defaults()
+        )
+      )
 
       group.addTask {
         try await client.run()

+ 9 - 7
Examples/v2/hello-world/Subcommands/Serve.swift

@@ -26,17 +26,19 @@ struct Serve: AsyncParsableCommand {
   var port: Int = 31415
 
   func run() async throws {
-    let http2 = HTTP2ServerTransport.Posix(
-      address: .ipv4(host: "127.0.0.1", port: self.port),
-      config: .defaults(transportSecurity: .plaintext)
+    let server = GRPCServer(
+      transport: .http2NIOPosix(
+        address: .ipv4(host: "127.0.0.1", port: self.port),
+        config: .defaults(transportSecurity: .plaintext)
+      ),
+      services: [Greeter()]
     )
 
-    let server = GRPCServer(transport: http2, services: [Greeter()])
-
     try await withThrowingDiscardingTaskGroup { group in
       group.addTask { try await server.run() }
-      let address = try await http2.listeningAddress
-      print("Greeter listening on \(address)")
+      if let address = try await server.listeningAddress {
+        print("Greeter listening on \(address)")
+      }
     }
   }
 }

+ 1 - 1
Sources/GRPCCore/GRPCServer.swift

@@ -74,7 +74,7 @@ public struct GRPCServer: Sendable {
   typealias Stream = RPCStream<ServerTransport.Inbound, ServerTransport.Outbound>
 
   /// The ``ServerTransport`` implementation that the server uses to listen for new requests.
-  private let transport: any ServerTransport
+  public let transport: any ServerTransport
 
   /// The services registered which the server is serving.
   private let router: RPCRouter

+ 41 - 0
Sources/GRPCHTTP2Core/ListeningServerTransport.swift

@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024, gRPC Authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public import GRPCCore
+
+/// A transport which refines `ServerTransport` to provide the socket address of a listening
+/// server.
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
+public protocol ListeningServerTransport: ServerTransport {
+  /// Returns the listening address of the server transport once it has started.
+  var listeningAddress: SocketAddress { get async throws }
+}
+
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
+extension GRPCServer {
+  /// Returns the listening address of the server transport once it has started.
+  ///
+  /// This will be `nil` if the transport doesn't conform to ``ListeningServerTransport``.
+  public var listeningAddress: SocketAddress? {
+    get async throws {
+      if let listener = self.transport as? (any ListeningServerTransport) {
+        return try await listener.listeningAddress
+      } else {
+        return nil
+      }
+    }
+  }
+}

+ 40 - 4
Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift

@@ -59,8 +59,8 @@ extension HTTP2ClientTransport {
     ///
     /// - Parameters:
     ///   - target: A target to resolve.
-    ///   - resolverRegistry: A registry of resolver factories.
     ///   - config: Configuration for the transport.
+    ///   - resolverRegistry: A registry of resolver factories.
     ///   - serviceConfig: Service config controlling how the transport should establish and
     ///       load-balance connections.
     ///   - eventLoopGroup: The underlying NIO `EventLoopGroup` to run connections on. This must
@@ -69,8 +69,8 @@ extension HTTP2ClientTransport {
     /// - Throws: When no suitable resolver could be found for the `target`.
     public init(
       target: any ResolvableTarget,
+      config: Config,
       resolverRegistry: NameResolverRegistry = .defaults,
-      config: Config = .defaults,
       serviceConfig: ServiceConfig = ServiceConfig(),
       eventLoopGroup: any EventLoopGroup = .singletonMultiThreadedEventLoopGroup
     ) throws {
@@ -180,13 +180,18 @@ extension HTTP2ClientTransport.Posix {
     }
 
     /// Default values.
-    public static var defaults: Self {
-      Self(
+    ///
+    /// - Parameters:
+    ///   - configure: A closure which allows you to modify the defaults before returning them.
+    public static func defaults(_ configure: (_ config: inout Self) -> Void = { _ in }) -> Self {
+      var config = Self(
         http2: .defaults,
         backoff: .defaults,
         connection: .defaults,
         compression: .defaults
       )
+      configure(&config)
+      return config
     }
   }
 }
@@ -202,3 +207,34 @@ extension GRPCChannel.Config {
     )
   }
 }
+
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
+extension ClientTransport where Self == HTTP2ClientTransport.Posix {
+  /// Creates a new Posix based HTTP/2 client transport.
+  ///
+  /// - Parameters:
+  ///   - target: A target to resolve.
+  ///   - config: Configuration for the transport.
+  ///   - resolverRegistry: A registry of resolver factories.
+  ///   - serviceConfig: Service config controlling how the transport should establish and
+  ///       load-balance connections.
+  ///   - eventLoopGroup: The underlying NIO `EventLoopGroup` to run connections on. This must
+  ///       be a `MultiThreadedEventLoopGroup` or an `EventLoop` from
+  ///       a `MultiThreadedEventLoopGroup`.
+  /// - Throws: When no suitable resolver could be found for the `target`.
+  public static func http2NIOPosix(
+    target: any ResolvableTarget,
+    config: HTTP2ClientTransport.Posix.Config,
+    resolverRegistry: NameResolverRegistry = .defaults,
+    serviceConfig: ServiceConfig = ServiceConfig(),
+    eventLoopGroup: any EventLoopGroup = .singletonMultiThreadedEventLoopGroup
+  ) throws -> Self {
+    return try HTTP2ClientTransport.Posix(
+      target: target,
+      config: config,
+      resolverRegistry: resolverRegistry,
+      serviceConfig: serviceConfig,
+      eventLoopGroup: eventLoopGroup
+    )
+  }
+}

+ 33 - 3
Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift

@@ -28,7 +28,7 @@ import NIOSSL
 extension HTTP2ServerTransport {
   /// A NIOPosix-backed implementation of a server transport.
   @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
-  public struct Posix: ServerTransport {
+  public struct Posix: ServerTransport, ListeningServerTransport {
     private let address: GRPCHTTP2Core.SocketAddress
     private let config: Config
     private let eventLoopGroup: MultiThreadedEventLoopGroup
@@ -370,16 +370,23 @@ extension HTTP2ServerTransport.Posix {
     }
 
     /// Default values for the different configurations.
+    ///
+    /// - Parameters:
+    ///   - transportSecurity: The security settings applied to the transport.
+    ///   - configure: A closure which allows you to modify the defaults before returning them.
     public static func defaults(
-      transportSecurity: TransportSecurity
+      transportSecurity: TransportSecurity,
+      configure: (_ config: inout Self) -> Void = { _ in }
     ) -> Self {
-      Self(
+      var config = Self(
         compression: .defaults,
         connection: .defaults,
         http2: .defaults,
         rpc: .defaults,
         transportSecurity: transportSecurity
       )
+      configure(&config)
+      return config
     }
   }
 }
@@ -421,3 +428,26 @@ extension ServerBootstrap {
     }
   }
 }
+
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
+extension ServerTransport where Self == HTTP2ServerTransport.Posix {
+  /// Create a new `Posix` based HTTP/2 server transport.
+  ///
+  /// - Parameters:
+  ///   - address: The address to which the server should be bound.
+  ///   - config: The transport configuration.
+  ///   - eventLoopGroup: The underlying NIO `EventLoopGroup` to the server on. This must
+  ///       be a `MultiThreadedEventLoopGroup` or an `EventLoop` from
+  ///       a `MultiThreadedEventLoopGroup`.
+  public static func http2NIOPosix(
+    address: GRPCHTTP2Core.SocketAddress,
+    config: HTTP2ServerTransport.Posix.Config,
+    eventLoopGroup: MultiThreadedEventLoopGroup = .singletonMultiThreadedEventLoopGroup
+  ) -> Self {
+    return HTTP2ServerTransport.Posix(
+      address: address,
+      config: config,
+      eventLoopGroup: eventLoopGroup
+    )
+  }
+}

+ 31 - 5
Sources/GRPCHTTP2TransportNIOTransportServices/HTTP2ServerTransport+TransportServices.swift

@@ -26,7 +26,7 @@ internal import NIOHTTP2
 extension HTTP2ServerTransport {
   /// A NIO Transport Services-backed implementation of a server transport.
   @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
-  public struct TransportServices: ServerTransport {
+  public struct TransportServices: ServerTransport, ListeningServerTransport {
     private let address: GRPCHTTP2Core.SocketAddress
     private let config: Config
     private let eventLoopGroup: NIOTSEventLoopGroup
@@ -145,7 +145,7 @@ extension HTTP2ServerTransport {
     ///   - eventLoopGroup: The ELG from which to get ELs to run this transport.
     public init(
       address: GRPCHTTP2Core.SocketAddress,
-      config: Config = .defaults,
+      config: Config,
       eventLoopGroup: NIOTSEventLoopGroup = .singletonNIOTSEventLoopGroup
     ) {
       self.address = address
@@ -282,7 +282,6 @@ extension HTTP2ServerTransport {
       self.serverQuiescingHelper.initiateShutdown(promise: nil)
     }
   }
-
 }
 
 @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
@@ -317,13 +316,18 @@ extension HTTP2ServerTransport.TransportServices {
     }
 
     /// Default values for the different configurations.
-    public static var defaults: Self {
-      Self(
+    ///
+    /// - Parameter configure: A closure which allows you to modify the defaults before
+    ///     returning them.
+    public static func defaults(configure: (_ config: inout Self) -> Void = { _ in }) -> Self {
+      var config = Self(
         compression: .defaults,
         connection: .defaults,
         http2: .defaults,
         rpc: .defaults
       )
+      configure(&config)
+      return config
     }
   }
 }
@@ -368,4 +372,26 @@ extension NIOTSListenerBootstrap {
     }
   }
 }
+
+@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
+extension ServerTransport where Self == HTTP2ServerTransport.TransportServices {
+  /// Create a new `TransportServices` based HTTP/2 server transport.
+  ///
+  /// - Parameters:
+  ///   - address: The address to which the server should be bound.
+  ///   - config: The transport configuration.
+  ///   - eventLoopGroup: The underlying NIO `EventLoopGroup` to the server on. This must
+  ///       be a `NIOTSEventLoopGroup` or an `EventLoop` from a `NIOTSEventLoopGroup`.
+  public static func http2NIOTS(
+    address: GRPCHTTP2Core.SocketAddress,
+    config: HTTP2ServerTransport.TransportServices.Config,
+    eventLoopGroup: NIOTSEventLoopGroup = .singletonNIOTSEventLoopGroup
+  ) -> Self {
+    return HTTP2ServerTransport.TransportServices(
+      address: address,
+      config: config,
+      eventLoopGroup: eventLoopGroup
+    )
+  }
+}
 #endif

+ 16 - 15
Sources/interoperability-tests/InteroperabilityTestsExecutable.swift

@@ -38,15 +38,15 @@ struct InteroperabilityTestsExecutable: AsyncParsableCommand {
     var port: Int
 
     func run() async throws {
-      var transportConfig = HTTP2ServerTransport.Posix.Config.defaults(
-        transportSecurity: .plaintext
-      )
-      transportConfig.compression.enabledAlgorithms = .all
-      let transport = HTTP2ServerTransport.Posix(
-        address: .ipv4(host: "0.0.0.0", port: self.port),
-        config: transportConfig
+      let server = GRPCServer(
+        transport: .http2NIOPosix(
+          address: .ipv4(host: "0.0.0.0", port: self.port),
+          config: .defaults(transportSecurity: .plaintext) {
+            $0.compression.enabledAlgorithms = .all
+          }
+        ),
+        services: [TestService()]
       )
-      let server = GRPCServer(transport: transport, services: [TestService()])
       try await server.run()
     }
   }
@@ -102,15 +102,16 @@ struct InteroperabilityTestsExecutable: AsyncParsableCommand {
     }
 
     private func buildClient(host: String, port: Int) throws -> GRPCClient {
-      var transportConfig = HTTP2ClientTransport.Posix.Config.defaults
-      transportConfig.compression.enabledAlgorithms = .all
       let serviceConfig = ServiceConfig(loadBalancingConfig: [.roundRobin])
-      let transport = try HTTP2ClientTransport.Posix(
-        target: .ipv4(host: host, port: port),
-        config: transportConfig,
-        serviceConfig: serviceConfig
+      return GRPCClient(
+        transport: try .http2NIOPosix(
+          target: .ipv4(host: host, port: port),
+          config: .defaults {
+            $0.compression.enabledAlgorithms = .all
+          },
+          serviceConfig: serviceConfig
+        )
       )
-      return GRPCClient(transport: transport)
     }
 
     private func runTest(

+ 6 - 5
Sources/performance-worker/PerformanceWorker.swift

@@ -50,12 +50,13 @@ struct PerformanceWorker: AsyncParsableCommand {
       print("[WARNING] performance-worker built in DEBUG mode, results won't be representative.")
     }
 
-    let transport = HTTP2ServerTransport.Posix(
-      address: .ipv4(host: "127.0.0.1", port: self.driverPort),
-      config: .defaults(transportSecurity: .plaintext)
+    let server = GRPCServer(
+      transport: .http2NIOPosix(
+        address: .ipv4(host: "127.0.0.1", port: self.driverPort),
+        config: .defaults(transportSecurity: .plaintext)
+      ),
+      services: [WorkerService()]
     )
-
-    let server = GRPCServer(transport: transport, services: [WorkerService()])
     try await server.run()
   }
 }

+ 6 - 2
Sources/performance-worker/WorkerService.swift

@@ -453,9 +453,13 @@ extension WorkerService {
 
     var clients = [BenchmarkClient]()
     for _ in 0 ..< config.clientChannels {
-      let transport = try HTTP2ClientTransport.Posix(target: target)
       let client = BenchmarkClient(
-        client: GRPCClient(transport: transport),
+        client: GRPCClient(
+          transport: try .http2NIOPosix(
+            target: target,
+            config: .defaults()
+          )
+        ),
         concurrentRPCs: Int(config.outstandingRpcsPerChannel),
         rpcType: rpcType,
         messagesPerStream: Int(config.messagesPerStream),

+ 10 - 5
Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOTransportServicesTests.swift

@@ -24,7 +24,8 @@ internal import XCTest
 final class HTTP2TransportNIOTransportServicesTests: XCTestCase {
   func testGetListeningAddress_IPv4() async throws {
     let transport = GRPCHTTP2Core.HTTP2ServerTransport.TransportServices(
-      address: .ipv4(host: "0.0.0.0", port: 0)
+      address: .ipv4(host: "0.0.0.0", port: 0),
+      config: .defaults()
     )
 
     try await withThrowingDiscardingTaskGroup { group in
@@ -43,7 +44,8 @@ final class HTTP2TransportNIOTransportServicesTests: XCTestCase {
 
   func testGetListeningAddress_IPv6() async throws {
     let transport = GRPCHTTP2Core.HTTP2ServerTransport.TransportServices(
-      address: .ipv6(host: "::1", port: 0)
+      address: .ipv6(host: "::1", port: 0),
+      config: .defaults()
     )
 
     try await withThrowingDiscardingTaskGroup { group in
@@ -62,7 +64,8 @@ final class HTTP2TransportNIOTransportServicesTests: XCTestCase {
 
   func testGetListeningAddress_UnixDomainSocket() async throws {
     let transport = GRPCHTTP2Core.HTTP2ServerTransport.TransportServices(
-      address: .unixDomainSocket(path: "/tmp/niots-uds-test")
+      address: .unixDomainSocket(path: "/tmp/niots-uds-test"),
+      config: .defaults()
     )
     defer {
       // NIOTS does not unlink the UDS on close.
@@ -87,7 +90,8 @@ final class HTTP2TransportNIOTransportServicesTests: XCTestCase {
 
   func testGetListeningAddress_InvalidAddress() async {
     let transport = GRPCHTTP2Core.HTTP2ServerTransport.TransportServices(
-      address: .unixDomainSocket(path: "/this/should/be/an/invalid/path")
+      address: .unixDomainSocket(path: "/this/should/be/an/invalid/path"),
+      config: .defaults()
     )
 
     try? await withThrowingDiscardingTaskGroup { group in
@@ -115,7 +119,8 @@ final class HTTP2TransportNIOTransportServicesTests: XCTestCase {
 
   func testGetListeningAddress_StoppedListening() async throws {
     let transport = GRPCHTTP2Core.HTTP2ServerTransport.TransportServices(
-      address: .ipv4(host: "0.0.0.0", port: 0)
+      address: .ipv4(host: "0.0.0.0", port: 0),
+      config: .defaults()
     )
 
     try? await withThrowingDiscardingTaskGroup { group in

+ 22 - 18
Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift

@@ -144,36 +144,40 @@ final class HTTP2TransportTests: XCTestCase {
 
     switch kind {
     case .posix:
-      var config = HTTP2ServerTransport.Posix.Config.defaults(transportSecurity: .plaintext)
-      config.compression.enabledAlgorithms = compression
-      let transport = HTTP2ServerTransport.Posix(
-        address: .ipv4(host: "127.0.0.1", port: 0),
-        config: config
+      let server = GRPCServer(
+        transport: .http2NIOPosix(
+          address: .ipv4(host: "127.0.0.1", port: 0),
+          config: .defaults(transportSecurity: .plaintext) {
+            $0.compression.enabledAlgorithms = compression
+          }
+        ),
+        services: services
       )
 
-      let server = GRPCServer(transport: transport, services: services)
       group.addTask {
         try await server.run()
       }
 
-      let address = try await transport.listeningAddress
+      let address = try await server.listeningAddress!
       return (server, address)
 
     case .niots:
       #if canImport(Network)
-      var config = HTTP2ServerTransport.TransportServices.Config.defaults
-      config.compression.enabledAlgorithms = compression
-      let transport = HTTP2ServerTransport.TransportServices(
-        address: .ipv4(host: "127.0.0.1", port: 0),
-        config: config
+      let server = GRPCServer(
+        transport: .http2NIOTS(
+          address: .ipv4(host: "127.0.0.1", port: 0),
+          config: .defaults {
+            $0.compression.enabledAlgorithms = compression
+          }
+        ),
+        services: services
       )
 
-      let server = GRPCServer(transport: transport, services: services)
       group.addTask {
         try await server.run()
       }
 
-      let address = try await transport.listeningAddress
+      let address = try await server.listeningAddress!
       return (server, address)
       #else
       throw XCTSkip("Transport not supported on this platform")
@@ -191,14 +195,14 @@ final class HTTP2TransportTests: XCTestCase {
 
     switch kind {
     case .posix:
-      var config = HTTP2ClientTransport.Posix.Config.defaults
-      config.compression.algorithm = compression
-      config.compression.enabledAlgorithms = enabledCompression
       var serviceConfig = ServiceConfig()
       serviceConfig.loadBalancingConfig = [.roundRobin]
       transport = try HTTP2ClientTransport.Posix(
         target: target,
-        config: config,
+        config: .defaults {
+          $0.compression.algorithm = compression
+          $0.compression.enabledAlgorithms = enabledCompression
+        },
         serviceConfig: serviceConfig
       )