gRPC Web and Gateway

Web browsers cannot make native gRPC calls. Many clients also expect plain REST and JSON. Two tools bridge the gap: gRPC Web serves browser applications, and a gateway exposes gRPC methods as REST endpoints. Both let one backend serve every kind of client.

Why Browsers Struggle

gRPC depends on low level HTTP/2 features, including trailers and precise control over frames. Browser scripting APIs hide those details. A page cannot build a raw gRPC request. A translation layer must sit between the browser and the gRPC server.

The Interpreter Analogy

Picture a conference with speakers of different languages. An interpreter in the middle translates each sentence. Neither side needs to learn the other language. A proxy plays that role for browsers and gRPC servers.

Browser ──gRPC Web──▶ Proxy ──gRPC──▶ Backend Service
Browser ◀─gRPC Web─── Proxy ◀─gRPC─── Backend Service

gRPC Web Basics

gRPC Web is a slightly adapted protocol that browsers can speak. A proxy such as Envoy converts it to regular gRPC. The browser client uses code generated from the same proto file as every other client.

const client = new UserServiceClient("https://api.example.com");
const request = new GetUserRequest();
request.setUserId("42");

client.getUser(request, {}, (err, reply) => {
  if (err) {
    console.error(err.message);
    return;
  }
  console.log(reply.getName());
});

gRPC Web Limits

Call TypeBrowser Support
UnarySupported
Server streamingSupported
Client streamingNot supported
Bidirectional streamingNot supported

Design browser facing methods around unary and server streaming calls. Use server streaming for live updates and a regular unary call for each user action.

REST Gateway

The grpc-gateway project generates a reverse proxy from annotations in your proto file. The proxy accepts REST requests with JSON bodies and forwards them as gRPC calls. Partners, scripts, and tools that only know REST can then use your service.

curl / mobile / partner ──HTTP + JSON──▶ Gateway ──gRPC──▶ Service
GET /v1/users/42                                  GetUser(user_id = "42")

Annotate the Proto File

import "google/api/annotations.proto";

service UserService {
  rpc GetUser (GetUserRequest) returns (User) {
    option (google.api.http) = {
      get: "/v1/users/{user_id}"
    };
  }

  rpc CreateUser (CreateUserRequest) returns (User) {
    option (google.api.http) = {
      post: "/v1/users"
      body: "*"
    };
  }
}

The path placeholder {user_id} maps to the request field with the same name. The setting body: "*" maps the JSON body to the request message.

Choosing a Bridge

ClientBest Option
Web application in the browsergRPC Web through a proxy
Partner using REST and JSONREST gateway
Mobile app you controlNative gRPC
Another internal serviceNative gRPC

Where to Run the Bridge

Run the proxy at the edge of your network, in front of the services. The edge hosts authentication, rate limits, and cross origin settings. Browsers enforce cross origin rules, so configure the proxy to allow your web domain and the gRPC Web headers.

Alternatives

The Connect protocol offers another route. A Connect server speaks gRPC, gRPC Web, and a simple HTTP and JSON format on the same port. Browsers call it directly with no proxy. Evaluate the option when a separate proxy feels heavy for your team.

Keep One Contract

All bridges build from the same proto file. A single contract keeps native gRPC, browser, and REST clients in agreement. Version the proto files with care, since every kind of client depends on them.

Summary

Browsers need gRPC Web and a proxy. REST clients need a gateway generated from proto annotations. Both options translate requests while the backend stays pure gRPC. One contract then serves every client type.