Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions src/middleware/route-check/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ type RouteCheckOptions = {
onNotFound?: (c: Context) => Response | Promise<Response>
}

/**
* Cache to store the result of handler checks.
*
* Determining if a handler is a "middleware" or an "actual handler" involves:
* 1. Unwrapping composed handlers recursively via `findTargetHandler`.
* 2. Checking the function length via `isMiddleware`.
*
* Since Hono handlers are immutable references in runtime, performing this calculation
* for every request is redundant. We use a `WeakMap` to cache the boolean result.
* This optimization:
* - Reduces CPU overhead by changing O(depth) recursion to O(1) map lookup.
* - Handles dynamic route registration safely (new handlers get new entries).
* - Prevents memory leaks (entries are GC'd when handlers are released).
*/
const handlerTypeCache = new WeakMap<Function, boolean>()

const isActualHandler = (handler: Function): boolean => {
if (handlerTypeCache.has(handler)) {
return handlerTypeCache.get(handler)!
}
const targetHandler = findTargetHandler(handler)
const result = !isMiddleware(targetHandler)
handlerTypeCache.set(handler, result)
return result
}

/**
* Route Check Middleware for Hono.
*
Expand Down Expand Up @@ -50,10 +76,7 @@ export const routeCheck = (options?: RouteCheckOptions): MiddlewareHandler => {
const routes = matchedRoutes(c)

// Check if there's at least one actual handler (not middleware)
const hasActualHandler = routes.some((route) => {
const targetHandler = findTargetHandler(route.handler)
return !isMiddleware(targetHandler)
})
const hasActualHandler = routes.some((route) => isActualHandler(route.handler))

if (!hasActualHandler) {
// No actual handler found - return 404 immediately
Expand Down