Middleware
Middleware lets you add functionality that runs before or after your service methods - like logging, authentication, or rate limiting. You write it once, and it applies to all (or some) of your methods automatically.What Is Middleware?
Think of middleware like security guards at a building entrance. Every visitor (request) passes through them before reaching their destination (your method). The guard can:- Check credentials - Is this person allowed in?
- Log the visit - Record who came and when
- Limit access - Only let 10 people in per minute
- Add information - Give them a visitor badge (add data to context)
Two Types of Middleware
Contract supports two levels of middleware:| Type | Level | Use For |
|---|---|---|
| Custom Invokers | Method calls | Logging, auth checks, metrics |
| HTTP Middleware | HTTP requests | CORS, request IDs, panic recovery |
Custom Invokers - Method-Level Middleware
The most common way to add middleware is by creating a custom invoker that wraps method calls.Basic Structure
Using Your Custom Invoker
Pass your invoker when mounting transports:Common Middleware Examples
Logging
Log every method call with timing:Authentication
Check if the user is logged in:Rate Limiting
Prevent too many requests:Metrics (Prometheus)
Track method calls for monitoring:Distributed Tracing
Add trace spans for debugging:Chaining Multiple Middleware
You often want multiple middleware together. Chain them by wrapping one inside another:Order Matters!
The order of middleware is important. Think about it like layers of an onion:- Logging first - logs everything, including rejected requests
- Metrics second - tracks all requests
- Rate limiting third - rejects before expensive checks
- Authentication fourth - before business logic
HTTP Middleware
For HTTP-level concerns (like CORS or request IDs), use standard Go HTTP middleware:CORS (Cross-Origin Requests)
Allow browsers from other domains to call your API:Request ID
Add a unique ID to every request for debugging:Panic Recovery
Catch panics and return proper errors:Authentication (Setting User in Context)
Extract user from token and add to context:Combining HTTP and Invoker Middleware
Use both together for complete coverage:- CORS - Allow cross-origin requests
- User - Extract user from token
- Request ID - Add tracking ID
- Recovery - Catch panics
- Logging - Log method calls
- Metrics - Track performance
- Auth - Verify user is authorized
- Your Method - Actually do the work
Passing Data Through Context
Context is how middleware shares data:Best Practices
1. Keep Middleware Focused
Each middleware should do one thing well:2. Don’t Do Heavy Work
Middleware runs on every request. Keep it fast:3. Handle Errors Properly
Use Contract’s error types for consistent handling:4. Make Middleware Configurable
See Also
- Service Definition - Writing services
- Error Handling - Return errors from middleware
- Architecture - How transports work
- Invokers - Deep dive into invokers