h3
h3 copied to clipboard
feat: add middleware meta support and defineMiddlewareRoute utility
Description
This PR introduces two new features to improve middleware handling in h3:
- Middleware meta support: Adds metadata support to middleware, similar to how routes can have meta
- 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?: H3RouteMetatoMiddlewareOptionstype - Updated
normalizeMiddlewareto handle meta and store it inevent.context.matchedMiddleware - Added
matchedMiddlewarearray toH3EventContexttype 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
defineMiddlewarefunction 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
What if we instead support defineRoute({ middleware: true, ... })? Most of spec looks similar other than it would call app.use instead of app.on
By the way, if the path does not enter, it automatically becomes global. path optional.