Skip to content
Created by

Using clients

Connect-Kotlin supports three protocols:

  • The Connect protocol, a simple, HTTP-based protocol that works over HTTP/1.1 or HTTP/2. It takes the best parts of gRPC/gRPC-Web, including streaming, and packages them into a protocol that works well on all platforms, including mobile. Supports both JSON- and binary-encoded Protobuf.
  • The gRPC protocol to talk to existing gRPC services.
  • The gRPC-Web protocol to talk to existing gRPC-Web services.

If your backend services are already using gRPC today, Envoy provides support for converting requests made using the Connect and gRPC-Web protocols to gRPC.

Switching between these protocols is a one-line code change to ProtocolClientConfig’s networkProtocol field:

val client = ProtocolClient(
httpClient = ConnectOkHttpClient(OkHttpClient()),
ProtocolClientConfig(
host = host,
serializationStrategy = GoogleJavaLiteProtobufStrategy(),
networkProtocol = NetworkProtocol.CONNECT, // NetworkProtocol.GRPC or NetworkProtocol.GRPC_WEB.
),
)

ProtocolClientConfig.serializationStrategy selects the message representation:

  • GoogleJavaLiteProtobufStrategy: Google Java lite types with Protobuf binary encoding. Smallest footprint; recommended for Android.
  • GoogleJavaProtobufStrategy: Google Java types with Protobuf binary encoding. Larger but with the complete Java reflection API.
  • GoogleJavaJSONStrategy: Google Java types with JSON encoding.

To switch strategies, change the strategy class and update the matching build settings:

Variantbuf.gen.yaml optProtobuf runtimeConnect-Kotlin extension
Java liteliteprotobuf-javalite + protobuf-kotlin-liteconnect-kotlin-google-javalite-ext
Java(none)protobuf-java + protobuf-kotlinconnect-kotlin-google-java-ext

GoogleJavaProtobufStrategy and GoogleJavaJSONStrategy use the Java variant. They differ only in wire format at runtime.

Gzip is enabled by default. For other algorithms, write a CompressionPool and register it; see GzipCompressionPool for reference.

By default, HTTP networking uses OkHttp via the ConnectOkHttpClient wrapper, which is just the OkHttp implementation of HTTPClientInterface. Its constructor accepts an OkHttpClient for the underlying network library. To swap in a different networking library, provide your own HTTPClientInterface implementation.

Generated clients expose Kotlin suspend methods for unary RPCs:

val client = ProtocolClient(
httpClient = ConnectOkHttpClient(OkHttpClient()),
ProtocolClientConfig(
host = "https://demo.connectrpc.com",
serializationStrategy = GoogleJavaLiteProtobufStrategy(),
networkProtocol = NetworkProtocol.CONNECT,
ioCoroutineContext = Dispatchers.IO, // Dispatch RPC I/O on Dispatchers.IO.
),
)
val elizaServiceClient = ElizaServiceClient(client)
lifecycleScope.launch {
val response = elizaServiceClient.say(sayRequest { sentence = "Hello, Eliza" })
response.success { success ->
println(success.message.sentence)
}
response.failure { error ->
// Handle any errors from the request.
}
}

For streaming RPCs, the client method returns a ServerOnlyStreamInterface (for server-streaming) or BidirectionalStreamInterface (for bidi) that lets you send messages and iterate over server responses using a ReceiveChannel:

val stream = elizaServiceClient.converse()
lifecycleScope.launch {
launch {
for (response in stream.responseChannel()) {
println(response.sentence)
}
}
stream.send(converseRequest { sentence = "Hello, Eliza" })
stream.sendClose()
}

If a callback-based approach is preferred, callbacks/closures can be used instead for unary methods. Streaming callback-based methods are not currently supported.

These methods are not generated by default, but are configurable using the generateCallbackMethods option:

val cancelable = elizaServiceClient.say(sayRequest { sentence = "hello" }) { response ->
response.success { result ->
println(result.message.sentence)
}
}
// cancelable() can be used to cancel the underlying request.