server/middleware

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.

4 min read Level 3/5 #nuxt#server#middleware
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 {}
h3 Utilities →