Proxy gRPC-Web directly in your Go Server (without envoy)

Roger Chapman
SafetyCulture Engineering
2 min readJul 26, 2019

“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.” — official gRPC-Web docs.

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 their own version of gRPC-Web; they also have a package that implements the gRPC-Web spec as a wrapper around a gRPC Go 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:

Originally published on the authors personal blog on July 26, 2019.

--

--

Roger Chapman
SafetyCulture Engineering

Software Engineer helping teams build scalable microservices in Go and gRPC