grpc-webnext
Full bidirectional gRPC for the browser — real HTTP/2 tunneled over WebSockets via h2ts, plus REST and JSON — served in front of any gRPC service.
The Rust server for grpc-webnext — it brings the complete gRPC experience (all four call types, deadlines, metadata, trailers, cancellation) to the browser, on the same port as native gRPC. Use it two ways:
- In-process — wrap a
tonicRoutesand serve grpc-webnext and nativeapplication/grpcfrom one listener, zero extra hops. - Standalone proxy — the
grpc-webnext-proxybinary fronts any gRPC upstream, in any language, no.protorequired (schema fetched via server reflection for the JSON/REST paths).
The browser side is the TypeScript client @grpc-webnext/client.
How it works
Two worlds share one endpoint; content-type and the WebSocket subprotocol disambiguate:
- Binary (default) → real gRPC over h2ts. The browser runs a real HTTP/2 stack tunneled over
a WebSocket by h2ts; this crate runs unmodified
tonicbehind an h2ts gateway. No translation — trailers, multiplexing, and flow control are native. - JSON (and binary
streaming: "ws") → the customFrameprotocol. Unary rides Fetch (trailer buffered into the body, since browsers can't read HTTP trailers); streaming is one WebSocket per stream. Plaintext JSON stays debuggable in the browser's Network tab. - REST →
google.api.httptranscoding. Annotate methods to expose real HTTP verbs and JSON bodies on REST URLs — the grpc-gateway / Envoy standard.
Native application/grpc clients pass through byte-for-byte on the same port.
Install
Library:
[]
= "0.1"
Proxy binary:
In-process — serve grpc-webnext + native gRPC on one port
use ;
async
Browsers reach it with @grpc-webnext/client; native gRPC clients (grpc-go, tonic, grpcurl…)
connect to the same address unchanged.
Proxy — front an existing gRPC server
UPSTREAM=http://localhost:50051 LISTEN=127.0.0.1:8080
The proxy is schema-agnostic. For the JSON/REST transcoding paths it fetches message descriptors
from the upstream via server reflection (SCHEMA=reflection) or a precompiled descriptor set
(DESCRIPTOR_SET=path). The binary passthrough (h2ts) path needs no schema at all.
Authorization
No bespoke hooks — authorization is a per-RPC concern, uniform across every transport: a tonic
interceptor in-process, or your mesh's ext_authz in front of the proxy.
Ecosystem
- Repository & docs: https://github.com/debdattabasu/grpc_webnext — normative
spec/PROTOCOL.mdand the language-neutral conformance suite. - Browser / Node client:
@grpc-webnext/client(npm). - h2ts — real HTTP/2 over WebSocket, the default transport: https://github.com/debdattabasu/h2ts.
License
Dual-licensed under either Apache-2.0 or MIT, at your option.