Nuxt 3 có hai loại middleware khác nhau:
Route Middleware (client + server): chạy khi navigating, kiểm soát routing:
typescript
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const { loggedIn } = useAuth()
if (!loggedIn.value && to.meta.requiresAuth) {
return navigateTo('/login')
}
})
// Dùng trong page
// pages/dashboard.vue
definePageMeta({ middleware: 'auth' })
// Inline middleware
definePageMeta({
middleware: [
async (to) => {
if (!canAccess(to)) return abortNavigation()
}
]
})Server Middleware (server-only): chạy trên server trước mọi request, giống Express middleware:
typescript
// server/middleware/logger.ts
export default defineEventHandler((event) => {
console.log(`[${event.method}] ${event.path}`)
// Không return gì → tiếp tục pipeline
})
// server/middleware/rate-limit.ts
export default defineEventHandler(async (event) => {
const ip = getRequestIP(event)
const count = await redis.incr(`rate:${ip}`)
if (count > 100) {
throw createError({ statusCode: 429, message: 'Too Many Requests' })
}
})Route Middleware (client + server): runs on navigation:
typescript
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
const { loggedIn } = useAuth()
if (!loggedIn.value && to.meta.requiresAuth)
return navigateTo('/login')
})
// In page
definePageMeta({ middleware: 'auth' })Server Middleware (server-only): runs before every request, like Express middleware:
typescript
// server/middleware/logger.ts
export default defineEventHandler((event) => {
console.log(`[${event.method}] ${event.path}`)
// Return nothing → continue
})
// Rate limiting
export default defineEventHandler(async (event) => {
const count = await redis.incr(`rate:${getRequestIP(event)}`)
if (count > 100) throw createError({ statusCode: 429 })
})