gRPC compatibility
Connect fully supports the gRPC and gRPC-Web protocols, including streaming. We validate our implementation of these protocols using an extended version of Google’s own interoperability tests.
Handlers
Section titled “Handlers”Handlers support the gRPC protocol by default: they work with tonic,
grpcurl, and any other gRPC client without any special configuration. Both
the built-in Server and axum::serve support HTTP/2 without TLS
(h2c), and the built-in Server supports TLS
with the server-tls feature.
Handlers also automatically support the binary gRPC-Web protocol directly,
without a translating proxy like Envoy. Since modern browsers all support
binary payloads, Connect doesn’t support gRPC-Web’s text mode: if you’re using
protoc-gen-grpc-web, you must use mode=grpcweb when generating code.
Many gRPC-specific tools depend on server reflection, which lets callers
access your service’s Protobuf schema at runtime. Connect supports server
reflection with the connectrpc-reflection crate.
Keep in mind that there are two versions of the gRPC server reflection API,
and many tools (including grpcurl) still use the older one —
connectrpc_reflection::install mounts both.
Container orchestration and health-checking systems often support the gRPC
health checking API. If you’d prefer gRPC-style health checks instead of more
traditional HTTP checks, use the connectrpc-health crate.
Clients
Section titled “Clients”Clients default to using the Connect protocol. To use the gRPC or gRPC-Web
protocols, call with_protocol on the client’s ClientConfig with
Protocol::Grpc or Protocol::GrpcWeb. The gRPC protocol requires HTTP/2. If
the gRPC server is using TLS, clients created with HttpClient::with_tls
negotiate HTTP/2 with no further configuration. If the gRPC server is using
HTTP/2 without TLS, create your client with HttpClient::plaintext_http2_only
as described in the deployment documentation:
use connectrpc::Protocol;use connectrpc::client::{ClientConfig, HttpClient};
let client = GreetServiceClient::new( HttpClient::plaintext_http2_only(), ClientConfig::new("http://localhost:8080".parse()?).with_protocol(Protocol::Grpc),);If you use HttpClient::plaintext instead, the client sends requests with
HTTP/1.1, and calls fail with an error like this:
internal: gRPC response missing grpc-status trailerMigration
Section titled “Migration”There’s no ironclad guide to migrating an existing tonic service to
connect-rust — every codebase uses a different subset of tonic
features and will need a slightly different approach. Unlike many RPC framework
migrations, remember that you do not need to modify your service’s clients:
they can continue to use their current gRPC clients. Your current Protobuf
schema will also work without modification.
The particulars of your codebase will be unique, but most migrations include a few common steps:
- Begin generating code with
buf.build/anthropics/buffaandbuf.build/connectrpc/rust. Connect for Rust uses buffa instead ofprostfor Protobuf messages, so the generated message types are different from the onestonicuses. During the migration, generate the Connect code into a separate module so your code can useconnect-rustandtoniccode without any problems. - Change your service implementations to implement the generated Connect
traits. Handlers receive a
RequestContextand a zero-copy view of the request instead of atonic::Request, and return aResponseinstead of atonic::Response. Rather than usingtonic::metadata, read request headers from theRequestContextand set response headers on theResponse. - Where necessary, change your service implementations to return
ConnectError. Connect and gRPC use the same error codes, so this is often a straightforward replacement oftonic::StatuswithConnectError. - Migrate any streaming handlers to use
InboundStreamandServiceStream. These are broadly similar to theirtonicequivalents. - Once you’ve migrated your service implementations to Connect, switch your
mainfunction to use Connect’sServer, or mount yourRouterin axum, instead oftonic::transport::Server. At this point, you’re halfway done: your service should compile, and you could deploy it without migrating your calls to downstream services. - Next, tackle your downstream calls. Switch to Connect’s generated client
types. Rather than wrapping requests in
tonic::Requestto set metadata, passCallOptionsto the_with_optionsmethods. Don’t forget to callwith_protocol(Protocol::Grpc)when configuring your client, and if necessary configure your HTTP clients to use h2c. - Where necessary, switch from
tonic::Statusandtonic::CodetoConnectErrorandErrorCode. - Migrate any streaming calls to the Connect stream types.
- You’re done! Unless your service is in the same repository as its clients,
you can stop generating code with
tonic.