gRPC-Web Demo

Unary RPC

A SayHello unary RPC sent from the browser over HTTP/1.1 via Gcore CDN β€” no Envoy required. The browser encodes the request as a binary Protobuf frame, nginx proxies it to a Node.js gRPC-Web server, which forwards it to a native gRPC backend over HTTP/2.

Architecture:

Browser (fetch + gRPC-Web framing) β†’ Gcore CDN (TLS termination, HTTP/2) β†’ nginx /grpc/ proxy_pass (HTTP/1.1) β†’ Node.js gRPC-Web proxy :9002 (HTTP/1.1 β†’ gRPC) β†’ Node.js gRPC server :50051 (HTTP/2)

Tech stack:

Protocol Buffers gRPC-Web HTTP/2 Node.js nginx Gcore CDN

Service definition (echo.proto)

The contract between client and server, language-agnostic:

syntax = "proto3";

service Echo {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest { string message = 1; }
message HelloReply   { string message = 1; }

Live call

Message to send:

Ready.

Request frame

POST /grpc/Echo/SayHello β€” Content-Type: application/grpc-web+proto

Protobuf payload:

gRPC-Web frame (flags + 4-byte length + payload):

flags length (BE uint32) protobuf payload

Response frame

Raw bytes returned by the server:

data flags length (BE uint32) protobuf payload trailer frame

Decoded reply:

gRPC trailers:

Why gRPC-Web instead of native gRPC?

Browsers cannot use native gRPC because they don't expose low-level HTTP/2 framing control. gRPC-Web is a thin adaptation that works over regular HTTP/1.1 fetch() calls, using a 5-byte binary envelope per message. A server-side proxy (here: Node.js, in production: Envoy) translates between the two protocols.

Native gRPC

  • HTTP/2 only
  • Binary Protobuf frames
  • Bidirectional streaming
  • Not supported in browsers
  • Test with grpcurl

gRPC-Web

  • HTTP/1.1 or HTTP/2
  • Same binary Protobuf payload
  • Unary + server streaming
  • Works in all browsers via fetch()
  • Requires a proxy on the server side