Resource caching is an effective strategy to improve performance and reduce load when running a service. Unfortunately, because gRPC requests use POST
requests, implementing caching for gRPC services the way one would with RESTful services is often cumbersome or impossible.
As part of our commitment to build a better RPC protocol, we’re pleased to announce that we have expanded the Connect protocol to support the use of HTTP GET
requests, enabling web browsers and CDNs to cache Connect requests with ease. Using connect-go 1.7.0 or greater, it is now possible to both handle and make GET
requests using RPCs, almost exactly the way it is done today with POST
, allowing web browsers and CDN services to cache Connect requests with ease.
In this article, we’ll discuss how to use this feature, where it’s useful, and show how existing gRPC services can be adapted to take advantage of this feature using Envoy.
Getting started with GET requests
To use HTTP GET
, RPC methods have to be annotated with the built-in Protobuf idempotency_level
option and specify NO_SIDE_EFFECTS
. This asserts that the RPC is safe to use as a GET
request (which can now be assumed when using both a Connect client and service). For example, here is how one might annotate the PetStore
example service:
service PetStore {
rpc GetPet(GetPetRequest) returns (GetPetResponse) {
option idempotency_level = NO_SIDE_EFFECTS;
}
rpc PutPet(PutPetRequest) returns (PutPetResponse) {}
rpc DeletePet(DeletePetRequest) returns (DeletePetResponse) {}
}
With this annotation, when buf generate
is invoked with connect-go 1.7 or newer, Connect servers will automatically support HTTP GET
requests—no other code modifications are needed.
On the client side, we need to instruct the Connect client to use GET
requests. In connect-go, this is done by specifying the WithHTTPGet()
option when creating a client:
client := petv1.NewPetStoreClient(
http.DefaultClient,
connect.WithHTTPGet(),
)
That’s it! This client will transparently use HTTP GET
when PetStore
methods without side effects are called.
Reference our documentation for more information.
Benefits of using GET requests with Connect
Now that we’ve discussed how to use GET
requests, let’s discuss why one might use GET
requests.
- Caching:
GET
requests are easy to cache, both in the browser and in most CDNs. It’s easy to set standard response headers likeCache-Control
to inform browsers, CDNs, and other middleboxes how to manage caching for a given request, and for how long the response is valid. - Ease of use:
GET
requests with JSON payloads are so easy to formulate, they can be written directly in a browser URL bar. This makes developing and testing programs simpler.
- Lower CORS overhead: Connect
GET
requests meet the requirements to avoid CORS preflight requests, as they don’t require any non-simple headers and useGET
, a simple method. This means fewer network round-trips for RPCs, a big win when dealing with unpredictable latency (such as when communicating over cellular networks). - And more!
GET
requests are versatile; it’s now possible to use Connect with tools that don’t necessarily speak the Connect protocol. Many programs can fetch an arbitrary URL and consume a JSON response; these tools can be used to make ConnectGET
requests. For example, now it’s possible to make Connect requests inside of Microsoft Power Query, or even use Connect APIs inside of Shortcuts on an iPhone or iPad.
Better gRPC interoperability with Envoy
Connect clients generally support communicating with vanilla gRPC and gRPC-web servers, but doing so prevents one from taking advantage of features unique to the Connect protocol. Users of the Envoy proxy will be pleased to know that Envoy 1.26 now ships with a Connect-gRPC bridge that allows clients to speak the Connect protocol (including GET
requests) to existing gRPC servers. This filter can be used without modifying any existing code. In addition, it doesn’t require configuration, gRPC reflection, or access to the underlying schema. That means it doesn’t need to be re-deployed when the underlying service changes, either—just set it and forget it!
To showcase this new capability, we created a demo showing how to use gRPC-Go with Envoy 1.26 to make GET
requests directly to a vanilla gRPC service.
Please note that this bridge filter is brand new and is not yet considered “stable” in Envoy, as it has not seen substantial testing in production environments.
We’re excited to see what these new features can enable and, more importantly, what we can do to continue to make Connect the best RPC protocol. Try the new GET
request feature and Envoy filter and let us know what you think via the Buf Slack. We’re always happy to chat about it!