This is a demonstrator project of how to make Browser-compatible requests against gRPC servers.
The biggest problem with Browser clients, is that although the vast majority of them support HTTP2,
do not support accessing Trailer
headers. A discussion is happening in fetch#34
to add them to the fetch
standard, but support is waay off.
The idea is to encode the values of Trailer
headers (including gRPC status codes) in a protobuf
(see terminator.proto that is sent as DATA
of the stream instead of as
headers. This makes it accessible to Browser clients through normal APIs. The presence of the
terminator is signalled by frame starting with 0xDEADE
and followed by a normal gRPC delimited message
containing the status code, status message and additional user trailers.
The implementation is an http.Handler
that acts as Middleware wrapping a grpc.Server
. It
intercepts the request and checks if a :grpc-browser-compat
header is contained within it. If not,
normal gRPC wire protocol semantics are followed. If it exists the Terminator proto is used.
Basically:
httpServer := http.Server{
Handler: grpc_browser_compat.Middleware(grpcServer),
}
You can make gRPC requests from a Browser-like clients. You need to prefix each message with the gRPC binary message delimiter) (5 bytes) and use protobuf encoding.
Together with protobuf.js and a dispatching client that uses jonnyreeves' chunked-request it should be possible to autogenerate gRPC clients in a browser.
TODO(michal): Update this section when work is done.
This kinda-sorta-works now. The gRPC Message Delimiters are written as Chunked-Encoding stream back to the client. This means that the response looks something like:
<chunk-length-in-ascii-int>\r\n
<grpc-message-delimiter><message-payload>
This is not ideal, as you have a double representation of the lenght of the message.
It would be possible to reimplement the grpc-message-delimiter as chunked encoded values, but its not needed now.
Binary protocols are hard to troubleshoot. Once the browser-end of the implementation is done, would
be useful to come up with an ASCII translation of the grpc-message-delimiter
making it easy to
debug.
More crucially, gRPC would have to support multiple codecs. See grpc-go#803