h3 icon indicating copy to clipboard operation
h3 copied to clipboard

feat: add middleware meta support and defineMiddlewareRoute utility

Open productdevbook opened this issue 5 months ago • 2 comments

Description

This PR introduces two new features to improve middleware handling in h3:

  1. Middleware meta support: Adds metadata support to middleware, similar to how routes can have meta
  2. defineMiddlewareRoute utility: A new utility function for defining middleware as plugins, following the same pattern as defineRoute

Motivation

Currently, middleware cannot carry metadata like routes can. This limits the ability to attach configuration or other information to middleware that can be accessed at runtime. Additionally, there's no plugin-based way to define middleware similar to defineRoute.

Changes

1. Middleware Meta Support

  • Added meta?: H3RouteMeta to MiddlewareOptions type
  • Updated normalizeMiddleware to handle meta and store it in event.context.matchedMiddleware
  • Added matchedMiddleware array to H3EventContext type to track matched middleware with their metadata

2. defineMiddlewareRoute Utility

  • New utility function that returns an H3Plugin for middleware registration
  • Supports path patterns, HTTP method filtering, and metadata
  • Uses the existing defineMiddleware function internally
  • Consistent API with defineRoute

Usage Examples

// Define middleware with meta
const authMiddleware = defineMiddlewareRoute({
  path: '/api/**',
  methods: ['POST', 'PUT', 'DELETE'],
  meta: { 
    requiresAuth: true,
    rateLimit: { interval: '1m', tokensPerInterval: 10 }
  },
  handler: async (event, next) => {
    if (\!event.context.user) {
      return new Response('Unauthorized', { status: 401 });
    }
    return next();
  }
});

// Register the middleware
app.register(authMiddleware);

// Access meta in handlers
app.get('/api/users', (event) => {
  // Access route meta
  const routeMeta = event.context.matchedRoute?.meta;
  
  // Access middleware meta
  const middlewareMeta = event.context.matchedMiddleware;
  // [{ route: '/api/**', meta: { requiresAuth: true, ... } }]
  
  return { users: [] };
});

Benefits

  • Consistent API between routes and middleware
  • Ability to attach configuration to middleware
  • Plugin-based middleware definition for better modularity
  • Follows existing h3 patterns and conventions

productdevbook avatar Jul 08 '25 18:07 productdevbook

What if we instead support defineRoute({ middleware: true, ... })? Most of spec looks similar other than it would call app.use instead of app.on

pi0 avatar Jul 08 '25 18:07 pi0

By the way, if the path does not enter, it automatically becomes global. path optional.

productdevbook avatar Jul 08 '25 18:07 productdevbook