In Process gRPC-Web Proxy

From the official gRPC-Web docs:

“gRPC-Web clients connect to gRPC services via a special gateway proxy: the current version of the library uses Envoy by default, in which gRPC-Web support is built-in.”

For production we can just enable the envoy.grpc_web filter and we are good to go.

But for development I wanted to create a gRPC server that engineers could install via a single binary and not have to run anything extra (like envoy running in docker).

gRPC-Web Wrapper

Prior to the release of the official gRPC-Web implementation the good guys at Improbable Engineering had created there own version of gRPC-Web and also have a grpcweb package that implements the gRPC-Web spec as a wrapper around a gRPC Go (Golang) Server.

Turns out that, with a little extra configuration, it can be made compatible with the official gRPC-Web client:

grpcServer := grpc. Server () grpcWebServer := grpcweb. WrapServer (grpcServer) httpServer = & http.Server{ Handler: h2c. NewHandler (http. HandlerFunc ( func (w http.ResponseWriter, r * http.Request) { if r.ProtoMajor == 2 { grpcWebServer. ServeHTTP (w, r) } else { w. Header (). Set ( "Access-Control-Allow-Origin" , "*" ) w. Header (). Set ( "Access-Control-Allow-Methods" , "POST, GET, OPTIONS, PUT, DELETE" ) w. Header (). Set ( "Access-Control-Allow-Headers" , "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-User-Agent, X-Grpc-Web" ) w. Header (). Set ( "grpc-status" , "" ) w. Header (). Set ( "grpc-message" , "" ) if grpcWebServer. IsGrpcWebRequest (r) { grpcWebServer. ServeHTTP (w, r) } } }), & http2.Server{}), }

Note: Were also using the golang.org/x/net/http2/h2c package to allow HTTP/2 over cleartext as we are also listening for HTTP/1.1 requests on the same port without TLS. This is not recommended for production, but means we don't require certificates during development.

Debugging gRPC-Web on the wire

For our frontend engineers they rely on chrome devtools to view network traffic, but for gRPC-Web it appears as a base64 string; not very useful.

So we created gRPC-Web Dev Tools a network like extension for Chrome that allows you to view the gRPC-Web requests and responses de-serialized to JSON objects; much better: