Middleware

Middleware is a fundamental concept in the Matrix Framework that allows you to process messages at various points in your application’s message flow.

What is Middleware?

Middleware functions are components that have access to the message context and the next middleware function in the application’s message-processing pipeline. They can:

  • Execute any code
  • Make changes to the message or context
  • End the message-processing pipeline
  • Call the next middleware in the pipeline

Middleware Structure

A middleware function has the following signature:

async function middleware(ctx: Context, next: Next) {
    // Pre-processing
    await next();
    // Post-processing
}

Key aspects:

  1. Context (ctx): Contains the current message and state
  2. Next: Function to call the next middleware
  3. Async/Await: Supports asynchronous operations

Common Use Cases

  1. Authentication

    async function authMiddleware(ctx: Context, next: Next) {
        if (!ctx.state.user) {
            throw new Error("Unauthorized");
        }
        await next();
    }
  2. Logging

    async function logMiddleware(ctx: Context, next: Next) {
        const start = Date.now();
        await next();
        const ms = Date.now() - start;
        console.log(`${ctx.path} - ${ms}ms`);
    }
  3. Error Handling

    async function errorMiddleware(ctx: Context, next: Next) {
        try {
            await next();
        } catch (err) {
            ctx.error = err;
            // Handle error appropriately
        }
    }

Middleware Order

The order of middleware is important:

  1. Middleware executes in the order it’s added
  2. Each middleware can control if the pipeline continues
  3. After next() is called, the code continues when the downstream middleware completes

Best Practices

  1. Keep it Focused

    • Each middleware should have a single responsibility
    • Break complex middleware into smaller, focused pieces
  2. Error Handling

    • Always use try-catch blocks
    • Pass errors to error-handling middleware
  3. State Management

    • Use ctx.state for passing data between middleware
    • Clean up state after use
  4. Performance

    • Keep middleware lightweight
    • Use async operations judiciously

Next Steps

Learn more about practical middleware implementations in the Features section.