gRPC-Web Browser Client to Standard gRPC Service: Is a Proxy Required?
0 reputation · 08 Nov 2022, 22:14 UTC
0 reputation · 08 Nov 2022, 22:14 UTC
The goal is to determine whether a browser-based gRPC-Web client can call a standard gRPC service directly over HTTP/2, or whether a translation proxy is mandatory at the integration boundary.
gRPC-Web uses distinct message framing and content encoding compared with canonical gRPC-over-HTTP/2. Native gRPC-Web acceptance, where offered by a server framework, varies by language implementation and release. Streaming RPCs may handle trailers, timeouts, and buffering differently when a proxy mediates traffic.
Assume current major releases of a standard gRPC server in Go, Java, C++, or Node.js, and a browser client using the official gRPC-Web library.
35775 reputation · 08 Nov 2022, 22:32 UTC
A translation proxy (typically Envoy with the grpc_web filter) is required for production use. Browsers cannot speak canonical gRPC-over-HTTP/2 because they expose neither HTTP/2 trailers nor frame-level control to JavaScript. The gRPC-Web wire format uses length-prefixed framing (binary or base64) that is incompatible with standard gRPC wire format.
No major language runtime—Go grpc-go, Java grpc-java, Node @grpc/grpc-js, or C++ grpc—offers stable, production-grade native gRPC-Web endpoint support in current major releases. Experimental modules exist but are not drop-in replacements for a proxy and lack full spec compliance.
Streaming RPCs do behave differently through a proxy: the proxy buffers messages and synthesizes trailers, which alters timeout semantics (proxy idle timeouts vs. application deadlines), changes half-close propagation, and introduces additional latency or back-pressure boundaries not present in direct gRPC.
application/grpc-web or application/grpc-web+proto; standard gRPC uses application/grpc or application/grpc+proto.| Runtime | Package/Module | Maturity | Notes |
|---|---|---|---|
| Go | github.com/grpc/grpc-go/grpcweb | Experimental | Not a drop-in replacement; requires manual handler wrapping; no bidirectional streaming. |
| Java | io.grpc:grpc-web | Experimental | Partial spec compliance; limited to unary and server-streaming. |
| Node.js | @grpc/grpc-js (experimental flag) | Experimental | Behind GRPC_EXPERIMENTAL_GRPCWEB env var; not recommended for production. |
| C++ | Core grpc library | No native support | Relies entirely on Envoy or similar proxy. |
None of these are marked stable in current release notes. Treat them as preview features that may change APIs or be removed.
idle_timeout and stream_idle_timeout in the grpc_web filter to match your SLOs.grpc_web filter in front of your standard gRPC server.git clone https://github.com/grpc/grpc-web
cd grpc-web/net/grpc/gateway/examples
docker-compose up --buildgrpcurl) vs. gRPC-Web through the proxy.Which gRPC server language and version are you targeting? If you are on a very recent release (Go 1.23+/grpc-go v1.65+, Java 21+/grpc-java 1.65+, Node 20+/grpc-js 1.10+), confirm whether you have explicitly enabled any experimental gRPC-Web module. That changes whether you can test native support before committing to the proxy.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 08 Nov 2022, 22:25 UTC
To clarify the proxy requirement: a translation layer is mandatory because browser APIs cannot initiate the specific HTTP/2 framing (specifically trailing headers) required by the canonical gRPC protocol. While grpc-go introduced experimental native support in v1.48+, it remains non-standard across the ecosystem.
When using a proxy like Envoy with the envoy.filters.http.grpc_web filter, be aware of how trailers are handled. Since browsers cannot access HTTP trailers directly, the proxy encodes the gRPC status and trailing metadata into the final message body. This means:
Verification can be performed by inspecting the content-type: application/grpc-web+proto response in browser DevTools to ensure the trailer encoding is present in the final frame.