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

browser / 3rd-party │ POST /spike/api/v1/proxy/email/send_email {json} ▼ grpc-gateway (generated reverse proxy) │ parse JSON → protobuf → gRPC call ▼ your gRPC server (ExternalSendEmail) │ protobuf response ▼ gateway encodes protobuf → JSON → HTTP response

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:

proto/spike/v1/email.proto:144 · cmd/server/spike/gserver.go:156
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)
Anchor — how it fronts gandalf spike and notification mount gateways at /{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.)
The loop closes This is the mechanism behind Lesson 14's "our repo does both": one .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.
Read this next

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…

It transcodes REST/JSON to gRPC and back, from the same proto — so you serve both.

Q2. The gateway learns its HTTP routes from…

The 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…

Via gateway.WithMetadata → so the same auth interceptor (Lesson 13) reads the token regardless of REST or gRPC entry.
What does grpc-gateway do, how does our repo use it, and what does it connect to?
recall, then click to reveal
grpc-gateway is a generated reverse proxy that transcodes REST/JSON ⇄ gRPC using 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.
🎓 Course complete — all 17 lessons From "what is gRPC" → Protobuf → the four RPC types → status, deadlines & metadata → interceptors, middleware & auth → architecture & the gateway. Every concept anchored to code you own. That's your third complete course. The last mile isn't more reading — it's retrieval under pressure. Ask me to run a mixed mock interview across all three courses (gRPC, Go, Kafka); where you're solid, I'll record it so we both know it's locked in.
Ready for the mock interview, or want to revisit any part in more depth (grpc-web, mTLS, streaming flow control)? Ask me.

1. gRPC-Gateway — Introduction.