Run Code on Every Request
server/middleware
Files in server/middleware/ run before any route handler — perfect for logging, auth checks, setting headers, or populating per-request context.
What you'll learn
- Create a middleware file under the server/middleware directory
- Use defineEventHandler without returning to fall through to the next handler
- Attach data to event.context for downstream handlers
Middleware in server/middleware/ runs on every request, before the matching route handler. It is
the right place for cross-cutting concerns: request logging, authentication, rate limiting, header
injection.
A Logging Middleware
// server/middleware/log.ts
export default defineEventHandler((event) => {
console.log(`[${event.method}] ${event.path}`)
}) Notice there’s no return value. When middleware returns nothing (or undefined), Nitro continues
to the next middleware or the route handler.
Setting Per-Request Context
event.context is a free-form object scoped to the current request. Middleware writes to it;
handlers read from it.
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
const token = getCookie(event, 'token')
if (token) {
event.context.user = await verifyToken(token)
}
}) Now any handler can read event.context.user:
// server/api/me.ts
export default defineEventHandler((event) => {
if (!event.context.user) {
throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
}
return event.context.user
}) Returning Early
To short-circuit, return a value from middleware. The route handler won’t run:
// server/middleware/maintenance.ts
export default defineEventHandler((event) => {
if (process.env.MAINTENANCE === '1') {
setResponseStatus(event, 503)
return { error: 'down for maintenance' }
}
}) Order
Middleware runs in alphabetical order by filename. Prefix with numbers when ordering matters:
server/middleware/01.cors.ts
server/middleware/02.auth.ts
server/middleware/03.log.ts Typing event.context
Augment the global type so TypeScript knows what you put on context:
// server/types.d.ts
declare module 'h3' {
interface H3EventContext {
user?: { id: string; name: string }
}
}
export {}