Description
When a project has nested route directories (e.g. routes/v2/ with a _middleware.dart, and sub-routes like routes/v2/person/[personId]/), the generated server.dart mounts all route handlers at the root router level with the most generic prefix first:
Handler buildRootHandler() {
final router = Router()
..mount('/v2', (context) => buildV2Handler()(context)) // generic — first
..mount('/v2/person', (context) => buildV2PersonHandler()(context))
..mount('/v2/person/', (context, personId) => ...) // specific — last
...
}
Since i had no idea i asked an AI that told me the following :
shelf_router falls through to the next matching mount when a handler returns 404. For a request to GET /v2/person/123/address:
/v2 matches → buildV2Handler pipeline runs v2_middleware → inner router has no route /person/123/address → 404 fallthrough
/v2/person matches → buildV2PersonHandler pipeline runs v2_middleware → inner router has no route /123/address → 404 fallthrough
/v2/person/ matches → buildV2PersonHandler pipeline runs v2_middleware + personId_middleware → inner router finds /address → 200
Result: v2_middleware executes 3 times for a single valid request. For a project where this middleware performs authentication (Keycloak token validation + DB call), this causes redundant network/DB calls on every request.
Steps To Reproduce
- Create a project with routes/v2/_middleware.dart and nested routes (routes/v2/person/[personId]/address.dart)
- Send a single GET /v2/person/123/address request
- Observe that any print or log in routes/v2/_middleware.dart appears multiple times
Expected Behavior
Each _middleware.dart should execute exactly once per request.
Additional Context
No response
Description
When a project has nested route directories (e.g. routes/v2/ with a _middleware.dart, and sub-routes like routes/v2/person/[personId]/), the generated server.dart mounts all route handlers at the root router level with the most generic prefix first:
Handler buildRootHandler() {
final router = Router()
..mount('/v2', (context) => buildV2Handler()(context)) // generic — first
..mount('/v2/person', (context) => buildV2PersonHandler()(context))
..mount('/v2/person/', (context, personId) => ...) // specific — last
...
}
Since i had no idea i asked an AI that told me the following :
shelf_router falls through to the next matching mount when a handler returns 404. For a request to GET /v2/person/123/address:
/v2 matches → buildV2Handler pipeline runs v2_middleware → inner router has no route /person/123/address → 404 fallthrough
/v2/person matches → buildV2PersonHandler pipeline runs v2_middleware → inner router has no route /123/address → 404 fallthrough
/v2/person/ matches → buildV2PersonHandler pipeline runs v2_middleware + personId_middleware → inner router finds /address → 200
Result: v2_middleware executes 3 times for a single valid request. For a project where this middleware performs authentication (Keycloak token validation + DB call), this causes redundant network/DB calls on every request.
Steps To Reproduce
Expected Behavior
Each _middleware.dart should execute exactly once per request.
Additional Context
No response