Creating Middleware

Learn how to create custom middleware for RouteMQ to process messages before they reach your route handlers.

Middleware Basics

Middleware in RouteMQ follows the "onion" pattern where each middleware wraps the next layer in the chain. All middleware must extend the base Middleware class and implement the handle method.

Basic Middleware Structure

from core.middleware import Middleware
from typing import Dict, Any, Callable, Awaitable

class YourMiddleware(Middleware):
    async def handle(self, context: Dict[str, Any], next_handler: Callable[[Dict[str, Any]], Awaitable[Any]]) -> Any:
        # Pre-processing: runs before the handler
        # Modify context, validate data, etc.
        
        # Call the next middleware or handler
        result = await next_handler(context)
        
        # Post-processing: runs after the handler
        # Modify response, log results, etc.
        
        return result

Understanding the Context

The context dictionary contains all information about the current message:

Simple Middleware Examples

Request Logging Middleware

Request ID Middleware

Data Validation Middleware

Advanced Middleware Patterns

Conditional Processing Middleware

Error Handling Middleware

Context Enhancement Middleware

Middleware with Configuration

Configurable Rate Limiting Middleware

Middleware with External Dependencies

Database Transaction Middleware

Redis Cache Middleware

Registration and Usage

Single Middleware

Multiple Middleware (Chain)

Group Middleware

Testing Middleware

Unit Testing

Integration Testing

Best Practices

1. Keep Middleware Focused

Each middleware should have a single responsibility:

2. Handle Errors Gracefully

3. Make Middleware Configurable

4. Document Context Modifications

5. Use Type Hints

Common Pitfalls

1. Forgetting to Call next_handler

2. Modifying Context Incorrectly

3. Not Handling Async Properly

Next Steps

Last updated