Skip to main content

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:
  1. Check credentials - Is this person allowed in?
  2. Log the visit - Record who came and when
  3. Limit access - Only let 10 people in per minute
  4. Add information - Give them a visitor badge (add data to context)

Two Types of Middleware

Contract supports two levels of middleware:

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:
Good ordering:
  1. Logging first - logs everything, including rejected requests
  2. Metrics second - tracks all requests
  3. Rate limiting third - rejects before expensive checks
  4. 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:
Flow:
  1. CORS - Allow cross-origin requests
  2. User - Extract user from token
  3. Request ID - Add tracking ID
  4. Recovery - Catch panics
  5. Logging - Log method calls
  6. Metrics - Track performance
  7. Auth - Verify user is authorized
  8. 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