Skip to content

Route Pattern-Based Hook Filtering #1570

@Kingflint

Description

@Kingflint

What is the problem this feature would solve?

Elysia lifecycle hooks apply either globally (all routes) or locally (single route). Developers cannot apply hooks to subsets of routes matching path patterns or HTTP methods without duplicating hook definitions or restructuring applications with .guard() and .group().

Use cases:
Apply authentication to /api/* but not /public/*
Rate limiting to POST/PUT/DELETE but not GET
Logging to specific path-method combinations

Current workarounds:
Repeat hook logic across routes
Nest routes in guard blocks, coupling structure to middleware
Write manual path-matching that executes on every request

What is the feature you are proposing to solve the problem?

Add pattern-based filtering for lifecycle hooks. Hooks accept an optional match property with path (glob pattern) and method (string or array) filters that determine which routes trigger hook execution.

API:

app.onBeforeHandle({ 
  match: { path: '/api/*', method: ['POST', 'PUT'] } 
}, handler)

Pattern Matching Behavior:

Path patterns:
/api/* matches single path segment after prefix (/api/users, not /api/users/123)
/api/ matches multiple segments (/api/users/123/posts)
/users/:id matches route parameters (/users/123, /users/abc)
/health matches exact path only

Method filters:
method: 'POST' matches single HTTP method
method: ['POST', 'PUT'] matches any method in array
Omitted method matches all HTTP methods
Case-insensitive comparison

Hook Execution:
Execute when route path matches pattern AND method matches filter
Multiple matching hooks execute in registration order
Non-matching hooks are skipped (zero overhead)

Applies to all lifecycle hooks:
onBeforeHandle
onAfterHandle
onTransform
onAfterResponse

What alternatives have you considered?

Using .group() and .guard():
Forces structural coupling between routing and middleware
Requires duplicating hooks across multiple groups for cross-cutting concerns
Cannot express patterns like "all POST/PUT/DELETE methods" without nesting

Manual path matching in hooks:
app.onBeforeHandle((ctx) => {
if (ctx.path.startsWith('/api/') && ['POST', 'PUT'].includes(ctx.method)) {
// logic here
}
})

Executes condition check on every request (performance overhead)
Duplicates pattern logic across multiple hooks
No reusable pattern abstraction

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions