Lesson 18 / 25

Interceptors

Middleware for RPCs.

Shared logic around every call

Interceptors wrap RPC handling on the client or server, like middleware: authentication and authorisation, logging, metrics, tracing, request ID propagation, input validation, panic recovery and rate limiting. There are unary and streaming interceptors, and they can be chained. Keep them small and focused, and order them deliberately, for example recovery and tracing first, then authentication, then logging.

A server auth interceptor in Go

Unary interceptor sketch using grpc-go.

func authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler) (any, error) {
    md, _ := metadata.FromIncomingContext(ctx)
    tokens := md.Get("authorization")
    if len(tokens) == 0 {
        return nil, status.Error(codes.Unauthenticated, "missing token")
    }
    user, err := verify(strings.TrimPrefix(tokens[0], "Bearer "))
    if err != nil {
        return nil, status.Error(codes.Unauthenticated, "invalid token")
    }
    if !allowed(user, info.FullMethod) {
        return nil, status.Error(codes.PermissionDenied, "not allowed")
    }
    return handler(withUser(ctx, user), req)
}

server := grpc.NewServer(grpc.ChainUnaryInterceptor(recoveryInterceptor, authInterceptor))

Remember streaming interceptors

A unary-only auth interceptor leaves streaming methods unprotected; register both kinds.

Quick check: What are gRPC interceptors comparable to?

  • Middleware that runs around each RPC
  • Protobuf messages
  • Database triggers only
  • Load balancers
Answer

Middleware that runs around each RPC — Cross-cutting logic.