Interceptors & Middleware
🧩 Interceptors & Middleware
express1-3).
The Problem: Repeating Logic in Every Method
Without interceptors, every single RPC method implementation would need to manually check auth metadata, log the call, and handle retries — repetitive, error-prone, and one new method away from someone forgetting the auth check entirely. This is exactly why Express middleware exists in the first place (express1-3): cross-cutting concerns don't belong duplicated inside every route handler.
Server Interceptors
A server interceptor wraps around every incoming call before it reaches the actual method handler — the same role app.use() middleware plays before Express route handlers run.
Every method handler defined in Chapter 3 now runs behind this check — none of them need to repeat the token-parsing logic Chapter 5's example wrote inline.
Client Interceptors
A client interceptor wraps around every outgoing call before it's actually sent — common uses include automatically attaching auth metadata to every call, retries with backoff, and logging.
Client code calling getProduct() no longer needs to manually build and pass a Metadata object with a token on every call site the way Chapter 5's raw example did — the interceptor attaches it automatically, exactly once, in one place.
Express Middleware vs. gRPC Interceptors
Express Middleware
app.use() registers a chain that runs before route handlers, each calling next() to pass control along — one direction, server-side only.
gRPC Interceptors
The same wrap-before-the-real-handler concept, but on both sides — server interceptors wrap incoming calls, client interceptors wrap outgoing ones.
| Use Case | Server or Client? | Example |
|---|---|---|
| Central auth check | Server | Reject unauthenticated calls before any handler runs |
| Auto-attaching auth metadata | Client | Every outgoing call gets a token automatically |
| Request/response logging | Either | Log every call attempt, regardless of outcome |
| Automatic retries | Client | Retry a call on UNAVAILABLE with backoff |
Server Interceptor Responsibilities
Anything that should apply uniformly to every incoming call before business logic runs — auth, rate limiting, request logging.
Client Interceptor Responsibilities
Anything that should apply to every outgoing call automatically — attaching credentials, retry logic, response-time logging.
💻 Coding Challenges
Challenge 1: Refactor Chapter 5's Auth Check
Chapter 5's getProduct handler manually checked auth metadata inline. Rewrite this as a server interceptor instead, so the handler itself no longer needs any auth-checking code.
Goal: Practice moving repeated per-method logic into a centralized interceptor.
Challenge 2: Server or Client Interceptor?
For each, say whether it belongs as a server interceptor or a client interceptor: (a) logging how long every call took to complete, (b) rejecting calls that exceed a rate limit, (c) automatically retrying a failed call up to 3 times.
Goal: Practice distinguishing responsibilities that belong on the receiving side from ones that belong on the calling side.
Challenge 3: Explain Interceptor Ordering
A team places their auth interceptor before their logging interceptor. Explain what this means for calls that get rejected by the auth interceptor, and propose a reordering if they want to log every attempt, including rejected ones.
Goal: Practice reasoning about interceptor order the same way you'd reason about Express middleware order.
Interceptors run in a chain, and — exactly like Express middleware — the order they're registered in determines what each one sees. If an auth interceptor runs first and rejects a call, any interceptor registered after it (a logging interceptor, say) never runs at all for that call, since the chain short-circuits at the rejection. This means a logging interceptor placed after auth silently misses every rejected/unauthenticated attempt — often exactly the calls worth logging most. If visibility into every attempt (including rejected ones) matters, logging needs to run before auth in the chain, not after — the same ordering discipline Express developers already apply to their own middleware stacks.
🎯 What's Next
The next chapter is Authentication & Security in gRPC — TLS by default, token-based auth via metadata in practice, and mutual TLS for service-to-service calls.