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 Type | Browser Support |
|---|---|
| Unary | Supported |
| Server streaming | Supported |
| Client streaming | Not supported |
| Bidirectional streaming | Not 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
| Client | Best Option |
|---|---|
| Web application in the browser | gRPC Web through a proxy |
| Partner using REST and JSON | REST gateway |
| Mobile app you control | Native gRPC |
| Another internal service | Native 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.
