gRPC Interceptor
distlimit provides both Unary and Streaming gRPC server interceptors via the github.com/balramadan/distlimit/middleware/grpc package.
Installation
Section titled “Installation”Install gRPC and distlimit using Go Modules:
go get google.golang.org/grpcgo get github.com/balramadan/distlimitBasic Setup
Section titled “Basic Setup”Attach UnaryServerInterceptor and StreamServerInterceptor when initializing your gRPC server:
package main
import ( "net" "time"
"github.com/balramadan/distlimit" "github.com/balramadan/distlimit/algorithm/tokenbucket" "github.com/balramadan/distlimit/driver/memory" distlimitgrpc "github.com/balramadan/distlimit/middleware/grpc" "google.golang.org/grpc")
func main() { // 1. Initialize Driver & Limiter (100 requests / minute) memDriver := memory.New(5 * time.Minute) limiter, _ := distlimit.New( memDriver, distlimit.WithLimit(100), distlimit.WithWindow(1*time.Minute), distlimit.WithAlgorithm(tokenbucket.New()), )
// 2. Register gRPC Interceptors server := grpc.NewServer( grpc.UnaryInterceptor(distlimitgrpc.UnaryServerInterceptor(limiter)), grpc.StreamInterceptor(distlimitgrpc.StreamServerInterceptor(limiter)), )
lis, _ := net.Listen("tcp", ":50051") _ = server.Serve(lis)}Configuration Options
Section titled “Configuration Options”Configure interceptor behavior by passing options into UnaryServerInterceptor(limiter, opts...) or StreamServerInterceptor(limiter, opts...):
| Option | Type | Description |
|---|---|---|
WithTrustedProxies(proxies) |
[]string |
CIDR blocks or IPs of trusted proxies for parsing x-forwarded-for metadata. |
WithKeyExtractor(fn) |
func(ctx context.Context) string |
Custom function to extract rate limit key from gRPC context/metadata. |
WithRouteLabeling(enable) |
bool |
Enables passing gRPC full method (info.FullMethod) into metric labels. |
Custom Key Extraction Example
Section titled “Custom Key Extraction Example”By default, distlimit rate limits requests based on client peer IP address. You can extract custom identifiers like gRPC metadata metadata or auth tokens using WithKeyExtractor:
grpc.UnaryServerInterceptor( limiter, distlimitgrpc.WithKeyExtractor(func(ctx context.Context) string { if md, ok := metadata.FromIncomingContext(ctx); ok { if tokens := md.Get("authorization"); len(tokens) > 0 { return "token:" + tokens[0] } } // Fallback to client peer IP address return distlimitgrpc.ExtractPeerIP(ctx, nil) }),)Response Headers & Error Behavior
Section titled “Response Headers & Error Behavior”Unlike HTTP servers that return 429 status codes, gRPC services handle rate limiting via status error responses.
When a client exceeds the allowed quota, distlimit rejects the unary or stream RPC call with gRPC status code codes.ResourceExhausted (numeric code 8):
rpc error: code = ResourceExhausted desc = rate limit exceeded for method /package.Service/Method: try again in 5 seconds