Middleware Routing in Astro
Astro middleware allows you to intercept requests, and change how they’re handled. For more advanced use-cases, you may want to run a middleware, or sequence of middlewares, on a specific set of routes. This guide shows you how to create a middleware router to customise on what routes each middleware is run.
This guide assumes you have an existing Astro project.
Install Dependencies
micromatch
is a powerful glob matching library, which can be used to match the pathnames of requests, to globs defined in the router. Install micromatch
and it’s types.
npm i micromatch# Install types as a devDependencynpm i -D @types/micromatch
Create the router
Create a function, that accepts a Record
of middleware. Get the entries, and return a middleware, using the defineMiddleware
type helper. The middleware should use the pathname to filter for every matching entry in the router, and create a sequence
using every matching middleware. It should call the sequence, passing along the arguments, before returning the response.
import type { MiddlewareResponseHandler } from 'astro'import { defineMiddleware, sequence } from 'astro:middleware'import micromatch from 'micromatch'
export function defineMiddlewareRouter(router: Record<string, MiddlewareResponseHandler>) { const entries = Object.entries(router) return defineMiddleware((context, next) => { return sequence( ...entries.filter(([path]) => micromatch.isMatch(context.url.pathname, path)) .map(([_, handler]) => handler) )(context, next) })}
Using the router
Import the defineMiddlewareRouter
function, and call it, passing an object. The key of each middleware is a glob, which is evaluated on each request. The router will match all globs, and execute them sequentially.
import { defineMiddlewareRouter } from './router'
export const onRequest = defineMiddlewareRouter({ '/api/*': (context, next) => { console.log('Calling API route') return next() }})
You can continue to use sequence
within the router.
import { defineMiddlewareRouter } from './router'import { defineMiddleware, sequence } from 'astro:middleware'
const validate = defineMiddleware(...)const auth = defineMiddleware(...)
export const onRequest = defineMiddlewareRouter({ '/dashboard/*': sequence(validate, auth)})