DEV Community

Steve Coffman
Steve Coffman

Posted on

Browser Client to gRPC Server Routing options: Connect, gRPC-web, gRPC-gateway and more!

Browser Client to gRPC Server Routing options: Connect, gRPC-web, gRPC-gateway and more!

These days, gRPC is commonly used and well-supported enough that many options exist for communicating to a gRPC backend from the browser.

For gRPC apps, I quite like using Connect. Connect is a family of libraries for building browser and gRPC-compatible HTTP APIs: you write a short Protocol Buffer schema and implement your application logic, and Connect generates code to handle marshaling, routing, compression, and content type negotiation. It also generates an idiomatic, type-safe client in any supported language.

Connect lets you choose from gRPC, gRPC-Web, and Connect's own protocol, but each protocol has a different set of production routing options.

Choosing a protocol and how to route it!

In Connect: Choosing a protocol shows connect supports gRPC-web as well, but I thought I'd expand on how routing works from the browser for these different protocol choices. As a refresher, this is from Connect's docs:

Connect has Seamless multi-protocol support

Connect servers and clients support three protocols: gRPC, gRPC-Web, and
Connect's own protocol.

  • Connect fully supports the gRPC protocol, including streaming, trailers, and error details. Any gRPC client, in any language, can call a Connect server, and Connect clients can call any gRPC server. We validate our gRPC compatibility with an extended version of Google's own interoperability tests.
  • Connect also offers direct support for the gRPC-Web protocol used by grpc/grpc-web, without relying on a translating proxy like Envoy.
  • Finally, Connect supports its own protocol: a straightforward HTTP-based protocol that works over HTTP/1.1, HTTP/2, and HTTP/3. It takes the best parts of gRPC and gRPC-Web, including streaming, and packages them into a protocol that's equally at home in browsers, monoliths, and microservices. By default, implementations support both JSON- and binary-encoded Protobuf. You can call our live demo service with cURL:


  curl \
      --header "Content-Type: application/json" \
      --data '{"sentence": "I feel happy."}' \
      https://demo.connectrpc.com/connectrpc.eliza.v1.ElizaService/Say


By default, Connect servers support ingress from all three protocols. Clients
default to using the Connect protocol, but can switch to gRPC or gRPC-Web with
a configuration toggle — no further code changes required. The APIs for
errors, headers, trailers, and streaming are all protocol-agnostic.


Connect protocol HTTP Host and Request Path Routing

We get to use traditional HTTP Routing!

The Connect protocol is a simple, POST-only protocol that works over HTTP/1.1 or HTTP/2 (or HTTP/3!). It takes the best portions of gRPC and gRPC-Web, including streaming, and packages them into a protocol that works equally well in browsers, monoliths, and microservices. The Connect protocol is what we think the gRPC Protocol should be. By default, JSON- and binary-encoded Protobuf is supported. Calling a Connect API is as easy as using curl:




# Try it out! This is a live demo!
curl \
    --header "Content-Type: application/json" \
    --data '{"sentence": "I feel happy."}' \
    https://demo.connectrpc.com/connectrpc.eliza.v1.ElizaService/Say


Enter fullscreen mode Exit fullscreen mode

Connect RPC Web

If you have a load balancer, you can use all the familiar HTTP/1.1 or HTTP/2 (or HTTP/3) routing rules to get to the backend (Host or Host+Path). This is my preferred option, and you can use your favorite load balancer. I like Envoy these days.

And inside your server, HTTP/1.1 or HTTP/2 (or HTTP/3) for the Connect protocol would be based on the URL /connectrpc.eliza.v1.ElizaService.


gRPC Routing

In Kubernetes, the common Gateway API spec has experimental support GRPCRoute. AFAICT Envoy Gateway has the most mature support for Gateway API GRPCRoute of the implementations. At least GKE specifically recommends using Envoy as your gRPC gateway.

The source code for that tutorial is here.

Note: Browsers do not support gRPC protocol natively because they do not support HTTP/2 Trailers, nor does the Browser's Fetch API support client streaming. The fetch API does specify streaming request bodies, but unfortunately, browser vendors have not come to an agreement to support streams from the client—see this WHATWG issue on GitHub. This means you can use streaming from the browser, but only server streaming.


gRPC-Gateway: JSON all the things

The gRPC-Gateway project started out after the original author,Yuki Yugui Sonoda, left Google and wanted to use a tool they had been using internally at Google, but couldn’t find an open-source version. So they wrote one!

At its core the gRPC-Gateway is a translation layer between the HTTP/JSON REStful API paradigm and the gRPC/Protobuf API paradigm.

Johan Brandhorst-Satzkorn wrote an excellent article on the ins and outs of gRPC-Gateway.

gRPC-Gateway JSON API

Vanguard: JSON all the things, but also Connect

Vanguard is a nearly seamless replacement for gRPC-Gateway. It replaces the JSON/REST to gRPC translation, but given that it also can translate JSON/REST to Connect, it opens up a few more options.


gRPC-web Routing options

There are two different options, and both of them involve using a proxy like Envoy.

gRPC-web Envoy proxy

grpc-web option 1: grpc-web

In grpc-web, traditional HTTP URL routing works. For instance:



curl 'http://localhost:8080/grpc.gateway.testing.EchoService/Echo' 
-H 'Pragma: no-cache' 
-H 'X-User-Agent: grpc-web-javascript/0.1' 
-H 'Origin: http://localhost:8081' 
-H 'Content-Type: application/grpc-web+proto' 
-H 'Accept: */*' 
-H 'X-Grpc-Web: 1' 
-H 'Connection: keep-alive' --data-binary $'\x00\x00\x00\x00\x05\n\x03abc' --compressed


Enter fullscreen mode Exit fullscreen mode

The URL /grpc.gateway.testing.EchoService would be routed to the service.

grpc-web option 2: gRPC bridging

Envoy also supports gRPC bridging where gRPC-web is translated to gRPC.

See https://github.com/connectrpc/envoy-demo/issues/2

Envoy notes

From Envoy HTTP/3 overview:

While HTTP/3 downstream support is deemed ready for production use, improvements are ongoing, tracked in the area-quic tag.

HTTP/3 upstream support is alpha - key features are implemented but have not been tested at scale.

https://github.com/envoyproxy/gateway/issues/422

From Gophers Slack regarding gRPC routing in GKE:

No particular opinions, it's fine. Google gave up on actually fixing their ingress controller and came up with the Gateway spec instead, It's not super widely supported in the rest of the k8s ecosystem yet. That said, it works very well on GKE for a lot of things.

For anything http1.1 it should work out of the box as an L7 LB.

For http2 to work properly it's likely that between the LB and app it needs to be configured to do TLS, because GCP LBs (regardless if configured with ingress or gateway) does not support h2c (http2 over cleartext) afaik. GKE only implements the HTTPRoute part of the Gateway spec also, so can't do anything protocol-aware for grpc or have tcp vs udp routes either.

Envoy Terminology

Top comments (1)

Collapse
 
jasspie profile image
Jason Li

Very well written 👏