---
title: "Middleware | Server"
description: "Apply custom middleware functions to intercept requests."
packages:
  - "@mastra/core"
---

# Middleware

Mastra servers can execute custom middleware functions before or after an API
route handler is invoked. This is useful for things like authentication,
logging, injecting request-specific context or adding CORS headers.

A middleware receives the [Hono](https://hono.dev) `Context` (`c`) and a `next`
function. If it returns a `Response` the request is short-circuited. Calling
`next()` continues processing the next middleware or route handler.

```typescript
import { Mastra } from "@mastra/core";

export const mastra = new Mastra({
  server: {
    middleware: [
      {
        handler: async (c, next) => {
          // Example: Add authentication check
          const authHeader = c.req.header("Authorization");
          if (!authHeader) {
            return new Response("Unauthorized", { status: 401 });
          }

          await next();
        },
        path: "/api/*",
      },
      // Add a global request logger
      async (c, next) => {
        console.log(`${c.req.method} ${c.req.url}`);
        await next();
      },
    ],
  },
});
```

To attach middleware to a single route pass the `middleware` option to
`registerApiRoute`:

```typescript
registerApiRoute("/my-custom-route", {
  method: "GET",
  middleware: [
    async (c, next) => {
      console.log(`${c.req.method} ${c.req.url}`);
      await next();
    },
  ],
  handler: async (c) => {
    const mastra = c.get("mastra");
    return c.json({ message: "Hello, world!" });
  },
});
```

---

## Common examples

### Using `RequestContext`

You can populate `RequestContext` dynamically in server middleware by extracting information from the request. In this example, the `temperature-unit` is set based on the Cloudflare `CF-IPCountry` header to ensure responses match the user's locale.

```typescript title="src/mastra/index.ts"
import { Mastra } from "@mastra/core";
import { RequestContext } from "@mastra/core/request-context";
import { testWeatherAgent } from "./agents/test-weather-agent";

export const mastra = new Mastra({
  agents: { testWeatherAgent },
  server: {
    middleware: [
      async (context, next) => {
        const country = context.req.header("CF-IPCountry");
        const requestContext = context.get("requestContext");

        requestContext.set(
          "temperature-unit",
          country === "US" ? "fahrenheit" : "celsius",
        );

        await next();
      },
    ],
  },
});
```

### Authentication

```typescript
{
  handler: async (c, next) => {
    const authHeader = c.req.header('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response('Unauthorized', { status: 401 });
    }

    // Validate token here
    await next();
  },
  path: '/api/*',
}
```

### CORS support

```typescript
{
  handler: async (c, next) => {
    c.header('Access-Control-Allow-Origin', '*');
    c.header(
      'Access-Control-Allow-Methods',
      'GET, POST, PUT, DELETE, OPTIONS',
    );
    c.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Authorization',
    );

    if (c.req.method === 'OPTIONS') {
      return new Response(null, { status: 204 });
    }

    await next();
  },
}
```

### Request logging

```typescript
{
  handler: async (c, next) => {
    const start = Date.now();
    await next();
    const duration = Date.now() - start;
    console.log(`${c.req.method} ${c.req.url} - ${duration}ms`);
  },
}
```

### Special Mastra headers

When integrating with Mastra Cloud or custom clients the following headers can
be inspected by middleware to tailor behavior:

```typescript
{
  handler: async (c, next) => {
    const isFromMastraCloud = c.req.header('x-mastra-cloud') === 'true';
    const clientType = c.req.header('x-mastra-client-type');
    const isStudio =
      c.req.header('x-studio') === 'true';

    if (isFromMastraCloud) {
      // Special handling
    }
    await next();
  },
}
```

- `x-mastra-cloud`: request originates from Mastra Cloud
- `x-mastra-client-type`: identifies the client SDK, e.g. `js` or `python`
- `x-studio`: request triggered from Studio

# Related

- [Request Context](/docs/v1/server/request-context)
