Routing

Routes in Finch are defined using FinchRoute objects collected inside a routing function. The routing function is registered with app.addRouting() and is called for every incoming request.

Routing Function

import 'package:finch/finch_route.dart';
import '../controllers/home_controller.dart';

final homeController = HomeController();

Future<List<FinchRoute>> getWebRoute(Request rq) async {
  return [
    FinchRoute(
      key: 'root',
      path: '/',
      methods: Methods.ONLY_GET,
      index: homeController.index,
    ),
  ];
}

Register it in app.dart:

app.addRouting(getWebRoute);

FinchRoute Parameters

Parameter Type Description
key String Unique route identifier. Used to generate URLs ($e.routeUrl('key'))
path String URL path segment. Supports {param} and wildcard *
methods List<String> Allowed HTTP methods. Use Methods constants
index Future<String> Function()? Handler function (no rq parameter; use Context.rq or a controller method)
controller Controller? Controller instance. Its index() is called when no index is set
children List<FinchRoute> Nested child routes. Path is relative to parent
extraPath List<String> Additional paths that map to the same route
auth AuthController? Authentication guard for this route
permissions List<String> Permission strings checked after auth
middlewares List<Middleware> Middleware chain executed before the handler
hosts List<String> Restrict to specific hostnames (['*'] = all)
ports List<int> Restrict to specific ports ([] = all)
params Map<String, dynamic> Default template parameters
excludePaths List<String> Sub-paths excluded from this route
apiDoc Future<ApiDoc>? Function()? API documentation for Swagger

HTTP Methods

// Convenience constants from Methods class:
Methods.ONLY_GET    // ['GET']
Methods.ONLY_POST   // ['POST']
Methods.ONLY_PUT    // ['PUT']
Methods.ONLY_DELETE // ['DELETE']
Methods.GET_POST    // ['POST', 'GET']
Methods.ALL         // All standard HTTP methods

// Or a custom list:
methods: [Methods.GET, Methods.POST, Methods.DELETE]

Path Parameters

Use {name} syntax to capture URL segments. Read them in the controller using rq.getParam('name'):

FinchRoute(
  key: 'users.show',
  path: 'users/{id}',
  methods: Methods.ONLY_GET,
  index: userController.show,
),
// In UserController:
Future<String> show() async {
  var id = rq.getParam('id');
  return rq.renderData(data: {'id': id});
}

Nested Routes (children)

Child route paths are relative to the parent path:

FinchRoute(
  key: 'example',
  path: 'example',
  index: homeController.redirectToRoot,
  children: [
    FinchRoute(
      key: 'example.form.get',
      path: 'form',
      methods: Methods.ONLY_GET,
      index: homeController.exampleForm,
    ),
    FinchRoute(
      key: 'example.form.post',
      path: 'form',
      methods: Methods.ONLY_POST,
      index: authController.loginPost,
    ),
    FinchRoute(
      key: 'example.panel',
      path: 'panel',
      methods: Methods.ALL,
      auth: authController,
      permissions: ['admin'],
      index: homeController.exampleAuth,
    ),
  ],
),

Extra Paths

extraPath maps additional URL prefixes to the same route and its children:

FinchRoute(
  key: 'root.mysql',
  path: 'example/mysql',
  extraPath: ['api/example/mysql'],
  methods: Methods.GET_POST,
  index: homeController.exampleMysql,
),

Host and Port Filtering

Restrict a route to specific hosts or ports:

FinchRoute(
  key: 'root.localhost',
  path: 'example/host',
  hosts: ['localhost'],
  ports: [80, 8085],
  index: homeController.renderLocalhost,
  methods: Methods.ALL,
),
FinchRoute(
  key: 'root.host',
  path: 'example/host',
  ports: [80, 8085],
  hosts: ['127.0.0.1'],
  index: homeController.render127001,
  methods: Methods.ALL,
),

Authentication Guard

Attach an AuthController to protect a route. If auth() returns false, the request is rejected before reaching the handler:

FinchRoute(
  key: 'admin.panel',
  path: 'admin/panel',
  auth: AppAuthController(),
  permissions: ['admin'],
  index: adminController.panel,
),

See Auth Controller for implementation details.

Route Caching

Use the .cache() extension to cache responses:

FinchRoute(
  key: 'root.route',
  path: 'example/route',
  methods: Methods.ONLY_GET,
  index: homeController.exampleRoute,
).cache(
  cacheDuration: Duration(minutes: 10),
  cacheType: [CacheParam.path, CacheParam.method, CacheParam.language],
  cacheSource: CacheSource.file,
),

See Route Cache for full details.

Generating URLs from Route Keys

In templates, use $e.routeUrl('key') to generate URLs:

<a href="{{ $e.routeUrl('example.panel') }}">Panel</a>
<a href="{{ $e.routeUrl('users.show', {'id': user.id}) }}">View User</a>

Get All Routes

Retrieve the full route list at runtime:

var routes = await app.getAllRoutes();