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: