Lesson 17 · Architecture & production
The gateway: HTTP/JSON transcoding
One .proto, two faces — how internal gRPC reaches external REST clients.
Your win: explain what grpc-gateway does and how our repo uses it to expose gRPC services as REST — closing the Lesson 14 loop and finishing the course.
The problem it solves
Lesson 14 left a gap: internal callers speak gRPC, but browsers and third parties need
REST/JSON. Rewriting each endpoint twice is waste. grpc-gateway
is a generated reverse proxy that transcodes REST/JSON ⇄ gRPC from the
same .proto.1
Driven by proto annotations
You add an option (google.api.http) to an RPC; codegen emits a
Register…HandlerFromEndpoint; you mount it on an HTTP mux:
rpc ExternalSendEmail(...) returns (...) {
option (google.api.http) = { post: "/spike/api/v1/proxy/email/send_email", body: "*" };
};
// SetupHTTP mounts a gateway.ServeMux at /spike/api/v1/proxy/*
spb.RegisterEmailModifierServiceHandlerFromEndpoint(ctx, mux, localGRPCAddr, opts)
/{service}/api/v1/proxy/*; the
gateway dials the local gRPC port and maps the HTTP Authorization header →
token metadata via gateway.WithMetadata (Lesson 10). This is
the layer behind the gandalf API gateway convention. (conversationmgmt
instead uses gin directly for its webhooks — a valid alternative when you don't want
full transcoding.)
.proto
defines the service; internal callers use the generated gRPC client; external callers
use REST that the gateway transcodes to that same gRPC. Write it once, serve it twice.
gRPC-Gateway — Introduction & docs
How the reverse proxy is generated from google.api.http annotations, and
the transcoding rules.
→ grpc-ecosystem.github.io/grpc-gateway
→ github.com/grpc-ecosystem/grpc-gateway
Check yourself (from memory)
Q1. grpc-gateway generates a…
Q2. The gateway learns its HTTP routes from…
option (google.api.http) on each RPC —
e.g. spike's POST …/send_email.
Q3. In our repo the gateway maps the HTTP Authorization header to…
gateway.WithMetadata → so the same auth
interceptor (Lesson 13) reads the token regardless of REST or gRPC entry.
option (google.api.http) annotations — an HTTP request comes
in, it parses JSON to protobuf, calls the gRPC server, and encodes the response back to
JSON, so one .proto serves both. Our repo annotates protos (e.g. spike's
ExternalSendEmail), codegen emits Register…HandlerFromEndpoint,
and SetupHTTP mounts a gateway.ServeMux at
/{service}/api/v1/proxy/*, mapping the HTTP Authorization
header → token metadata (L10). It fronts gandalf, the
external API gateway — closing the Lesson 14 loop.