From ac8b0b9d4975c64bea68f4594a61335fff87fae7 Mon Sep 17 00:00:00 2001 From: Erick Date: Thu, 8 Jun 2023 09:49:51 -0300 Subject: [PATCH] feat: add wildcard support on routes (#676) * initial commit * adding missing tests * docs * Update bricks/dart_frog_prod_server/hooks/pre_gen.dart * Apply suggestions from code review Co-authored-by: Scarlett Eliza * fix: docs format --------- Co-authored-by: Scarlett Eliza --- .../__brick__/server.dart | 2 +- .../__brick__/build/bin/server.dart | 2 +- docs/docs/basics/routes.md | 23 +++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/bricks/dart_frog_dev_server/__brick__/server.dart b/bricks/dart_frog_dev_server/__brick__/server.dart index d36c9876d..78ccfb855 100644 --- a/bricks/dart_frog_dev_server/__brick__/server.dart +++ b/bricks/dart_frog_dev_server/__brick__/server.dart @@ -32,7 +32,7 @@ Handler buildRootHandler() { Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}String {{.}},{{/directory_params}}) { final pipeline = const Pipeline(){{#middleware.0}}{{#middleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware){{/middleware}}{{/middleware.0}}; final router = Router() - {{#files}}..all('{{{route}}}', (context{{#file_params.0}},{{#file_params}}{{.}},{{/file_params}}{{/file_params.0}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,{{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/files}}; + {{#files}}{{#wildcard}}..mount('{{{route}}}', (context) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,context.request.url.path)){{/wildcard}}{{^wildcard}}..all('{{{route}}}', (context{{#file_params.0}},{{#file_params}}{{.}},{{/file_params}}{{/file_params.0}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,{{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/wildcard}}{{/files}}; return pipeline.addHandler(router); } {{/directories}} \ No newline at end of file diff --git a/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart b/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart index 4c2dc7c06..c1e5e28f8 100644 --- a/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart +++ b/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart @@ -34,7 +34,7 @@ Handler buildRootHandler() { Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}String {{.}},{{/directory_params}}) { final pipeline = const Pipeline(){{#middleware.0}}{{#middleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware){{/middleware}}{{/middleware.0}}; final router = Router() - {{#files}}..all('{{{route}}}', (context{{#file_params.0}},{{#file_params}}{{.}},{{/file_params}}{{/file_params.0}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,{{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/files}}; + {{#files}}{{#wildcard}}..mount('{{{route}}}', (context) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,context.request.url.path)){{/wildcard}}{{^wildcard}}..all('{{{route}}}', (context{{#file_params.0}},{{#file_params}}{{.}},{{/file_params}}{{/file_params.0}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(context,{{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/wildcard}}{{/files}}; return pipeline.addHandler(router); } {{/directories}} \ No newline at end of file diff --git a/docs/docs/basics/routes.md b/docs/docs/basics/routes.md index 8536d146f..c4e6ec863 100644 --- a/docs/docs/basics/routes.md +++ b/docs/docs/basics/routes.md @@ -416,6 +416,23 @@ Response onRequest(RequestContext context, String userId, String postId) { } ``` +## Wildcard Routes ♾ + +Dart Frog supports wildcard routes. For example, if you create a file called `routes/posts/[...page].dart`, then it will be accessible at any path that starts with `/posts/`, with any number of levels, allowing it to called from `/posts/today`, `/posts/features/stared`, and so forth. + +Routing parameters are forwarded to the `onRequest` method as seen below: + +```dart +import 'package:dart_frog/dart_frog.dart'; + +Response onRequest(RequestContext context, String page) { + return Response(body: 'post page: $page'); +} +``` + +```warning +Wildcard routes **must** be unique leaf routes on their route node, meaning that they need to be a file, and they need to be the only route in their folder. + ## Route Conflicts 💥 When defining routes, it's possible to encounter route conflicts. @@ -425,11 +442,13 @@ A route conflict occurs when more than one route handler resolves to the same en For example, given the following file structure: ``` + ├── routes │   ├── api │   │   └── index.dart │   └── api.dart -``` + +```` Both `routes/api/index.dart` and `routes/api.dart` resolve the the `/api` endpoint. @@ -439,7 +458,7 @@ When running the development server via `dart_frog dev`, Dart Frog will report r [hotreload] - Application reloaded. Route conflict detected. `routes/api.dart` and `routes/api/index.dart` both resolve to `/api`. -``` +```` When generating a production build via `dart_frog build`, Dart Frog will report all detected route conflicts and fail the build if one or more route conflicts are detected.