Skip to content

Route-Specific Middleware ​

Route-specific middleware applies to specific route patterns, allowing targeted functionality like authentication for API routes or logging for admin routes.

Basic Usage ​

Apply middleware to specific route patterns using the use() method with a route path:

typescript
import { Router } from '@neabyte/deserve'

const router = new Router()

// Route-specific middleware for /api/* routes
router.use('/api', async (ctx, next) => {
  console.log(`API request: ${ctx.request.method} ${ctx.url}`)
})

await router.serve(8000)

Route Pattern Matching ​

Middleware applies to routes that start with the specified pattern:

typescript
// Applies to /api/* routes
router.use('/api', middleware)

// Applies to /api/users/* routes
router.use('/api/users', middleware)

// Applies to /admin/* routes
router.use('/admin', middleware)

Common Route-Specific Patterns ​

API Authentication ​

typescript
// Require authentication for all API routes
router.use('/api', async (ctx, next) => {
  const authHeader = ctx.header('authorization')
  if (!authHeader) {
    return ctx.send.text('API requires authentication', { status: 401 })
  }
  // Validate token
  const token = authHeader.replace('Bearer ', '')
  if (!isValidToken(token)) {
    return ctx.send.text('Invalid token', { status: 401 })
  }
  // Context not modified, Handler automatically calls next()
})

Admin Authorization ​

typescript
// Require admin role for admin routes
router.use('/admin', async (ctx, next) => {
  const userRole = ctx.header('x-user-role')
  if (userRole !== 'admin') {
    return ctx.send.text('Admin access required', { status: 403 })
  }
  // Context not modified, Handler automatically calls next()
})

Public Route Logging ​

typescript
// Log all public route access
router.use('/public', async (ctx, next) => {
  console.log(`Public access: ${ctx.request.method} ${ctx.url}`)
})

Version-Specific Middleware ​

typescript
// Different middleware for API versions
router.use('/api/v1', async (ctx, next) => {
  // Legacy API behavior
  console.log('Legacy API v1 request')
})

router.use('/api/v2', async (ctx, next) => {
  // Modern API behavior
  console.log('Modern API v2 request')
})

Multiple Route-Specific Middleware ​

Apply multiple middleware to the same route pattern:

typescript
// Authentication middleware for API routes
router.use('/api', async (ctx, next) => {
  const authHeader = ctx.header('authorization')
  if (!authHeader) {
    return ctx.send.text('Unauthorized', { status: 401 })
  }
})

// Logging middleware for API routes
router.use('/api', async (ctx, next) => {
  console.log(`API: ${ctx.request.method} ${ctx.url}`)
})

Nested Route Patterns ​

Apply middleware to nested route patterns:

typescript
// General API middleware
router.use('/api', async (ctx, next) => {
  console.log('API request')
})

// Specific middleware for user routes
router.use('/api/users', async (ctx, next) => {
  console.log('User API request')
})

// Admin-specific middleware for user management
router.use('/api/users/admin', async (ctx, next) => {
  const role = ctx.header('x-user-role')
  if (role !== 'admin') {
    return ctx.send.text('Admin access required', { status: 403 })
  }
})

Middleware Execution Order ​

Middleware executes in the order it's added:

typescript
// Global middleware added first
router.use(async (ctx, next) => {
  console.log('Global middleware')
})

// Route-specific middleware added second
router.use('/api', async (ctx, next) => {
  console.log('API middleware')
})

// Execution order for /api/users:
// 1. Global middleware (added first)
// 2. API middleware (route-specific, added second)
// 3. Route handler

Released under the MIT License.