dart_frog icon indicating copy to clipboard operation
dart_frog copied to clipboard

feat: Mount non-dynamic routes first

Open videah opened this issue 2 years ago • 7 comments

Description

Currently dynamic directory routes get mounted first which leads to other routes in the same directory never getting matched.

For example, when you have routes like routes/api/[id]/index.dart and routes/api/status.dart the latter can never get matched. The generated code will always mount the first route first so the router will always pass status to [id].

Additional Context

Here is the root handler generated by dart_frog with my current project which implements the Mastodon API. Routes for the second mount such as/api/v1/accounts/search can never be reached.

Handler buildRootHandler() {
  final pipeline = const Pipeline().addMiddleware(middleware.middleware);
  final router = Router()
    ..mount('/api/v1/accounts/<id>', (context,id,) => buildApiV1Accounts$idHandler(id,)(context))
    ..mount('/api/v1/accounts', (context) => buildApiV1AccountsHandler()(context))
    ..mount('/api/v1/timelines', (context) => buildApiV1TimelinesHandler()(context))
    ..mount('/api/v1', (context) => buildApiV1Handler()(context))
    ..mount('/oauth', (context) => buildOauthHandler()(context))
    ..mount('/', (context) => buildHandler()(context));
  return pipeline.addHandler(router);
}

videah avatar Apr 29 '23 22:04 videah

Hi @videah, thanks for opening this issue!

I haven't attempted to reproduce this yet. Regardless, would you possibly be interested in contributing with a PR?

alestiago avatar May 09 '23 17:05 alestiago

I would take a stab at it but I'm not entirely sure how I go about creating a local dev environment for dart_frog 😅

videah avatar May 12 '23 20:05 videah

I was able to reproduce this using dart_frog_cli version 0.3.6, see this for the full sample.

Demo video

https://github.com/VeryGoodOpenSource/dart_frog/assets/44524995/14ee63bb-5180-44b9-8146-a62f3dfd34d2

alestiago avatar May 25 '23 14:05 alestiago

For reference, we should definitely support this.

Here is a section of the OpenApi specification where the behaviour is mentioned.

alestiago avatar Jun 03 '23 08:06 alestiago

@videah unfortunately, changing the order of the mounting of the routes in such a proposed way will not be able at the moment.

We have spent time working on implementing a different order to make it possible for non-dynamic and dynamic routes that would listen to similar endpoint be able to respond to their specific urls, but we faced a couple of issues. We actually got the precedence to work as expected, but that generated complicated side effects for middlewares.

Since both GET routes/api/status and GET routes/api/XXXX would be able to handled from routes/api/[id]/index.dart and given the complications mentioned above we decided to keep as is and implement a conflict detection (#687), so at least, the developer will be notified of the conflict and issues will not go unnoticeable.

erickzanardo avatar Jun 06 '23 14:06 erickzanardo

Now that we have the validation in place, I will mark this as an enhancement so we can try to come back to it in there future after we had the code gen restructure.

erickzanardo avatar Jun 08 '23 13:06 erickzanardo