Open-Source Wikis

/

Astro

/

Features

/

Middleware

withastro/astro

Middleware

A user-defined function in src/middleware.ts that wraps every request before it reaches a page or endpoint. Astro composes user middleware with internal middleware (i18n, CSP) into a single chain.

Purpose

  • Run code on every request (auth checks, request logging, header injection).
  • Mutate context.locals so pages and endpoints have shared per-request state.
  • Short-circuit a request to return a different Response.

Key files

File Purpose
packages/astro/src/core/middleware/index.ts Public exports: defineMiddleware, sequence.
packages/astro/src/core/middleware/sequence.ts The sequence(...mws) combinator.
packages/astro/src/core/middleware/callMiddleware.ts Runs the chain with a next function.
packages/astro/src/core/middleware/defineMiddleware.ts The defineMiddleware typed-helper.
packages/astro/src/core/middleware/noop-middleware.ts Used when no user middleware exists.
packages/astro/src/core/middleware/vite-plugin.ts Emits the astro:middleware virtual module + the user-middleware loader.
packages/astro/src/i18n/middleware.ts The framework-internal i18n middleware.

Authoring

// src/middleware.ts
import { defineMiddleware, sequence } from 'astro:middleware';

const auth = defineMiddleware(async (context, next) => {
  context.locals.user = await loadUser(context.cookies.get('session'));
  return next();
});

const headers = defineMiddleware(async (context, next) => {
  const response = await next();
  response.headers.set('x-server-version', '1');
  return response;
});

export const onRequest = sequence(auth, headers);

onRequest is the convention; export const onRequest = ... is what the framework picks up.

Execution order

graph LR
    A[Request] --> B[i18n middleware]
    B --> C[User onRequest middleware]
    C --> D[Internal CSP middleware]
    D --> E[Render page or endpoint]
    E --> F[Response]
    F --> D
    D --> C
    C --> B
    B --> G[Caller]

Internal middleware (i18n, CSP) is inserted by the framework around user middleware. The order is enforced by core/middleware/sequence.ts and vite-plugin.ts.

Public API

astro:middleware exports:

  • defineMiddleware(fn) — typed wrapper.
  • sequence(...fns) — compose multiple middleware.
  • MiddlewareHandler, MiddlewareNext types.
  • MiddlewareResponseHandler for response-only handlers.

The same names are also re-exported from astro/middleware for use in tooling.

Common mistakes

  • Forgetting await next() — your downstream middleware/page never runs.
  • Mutating context after next() returnscontext.locals is a regular object, not reactive; mutate before calling next().
  • Throwing from inside middleware — caught by RenderContext and rendered as the configured 500 page (or the dev overlay in dev). Use AstroUserError for user-facing problems.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Middleware – Astro wiki | Factory