Routering
Routes in Finch worden gedefinieerd met FinchRoute-objecten die zijn verzameld in een routeringsfunctie. De routeringsfunctie wordt geregistreerd met app.addRouting() en wordt aangeroepen voor elk binnenkomend verzoek.
Routeringsfunctie
import 'package:finch/finch_route.dart';
import '../controllers/home_controller.dart';
final homeController = HomeController();
Future<List<FinchRoute>> getWebRoute() async {
return [
FinchRoute(
key: 'root',
path: '/',
methods: Methods.ONLY_GET,
index: homeController.index,
),
];
}
Registreer het in app.dart:
app.addRouting(getWebRoute);
FinchRoute-parameters
| Parameter | Type | Beschrijving |
|---|---|---|
key |
String |
Unieke route-identificator. Wordt gebruikt om URL's te genereren ($e.routeUrl('key')) |
path |
String |
URL-padsegment. Ondersteunt {param} of :param en wildcard * |
methods |
List<String> |
Toegestane HTTP-methoden. Gebruik Methods-constanten |
index |
Future<String> Function()? |
Handlerfunctie (geen rq-parameter; gebruik Context.rq of een controllermethode) |
controller |
Controller? |
Controller-instantie. index() wordt aangeroepen wanneer er geen index is ingesteld |
children |
List<FinchRoute> |
Geneste kindroutes. Pad is relatief ten opzichte van de ouder |
extraPath |
List<String> |
Extra paden die naar dezelfde route verwijzen |
auth |
AuthController? |
Authenticatiebeveiliging voor deze route |
permissions |
List<String> |
Permissiestrings die na auth worden gecontroleerd |
middlewares |
List<Middleware> |
Middleware-keten die vóór de handler wordt uitgevoerd |
hosts |
List<String> |
Beperk tot specifieke hostnamen (['*'] = alle) |
ports |
List<int> |
Beperk tot specifieke poorten ([] = alle) |
params |
Map<String, dynamic> |
Standaard sjabloonparameters |
excludePaths |
List<String> |
Subpaden die zijn uitgesloten van deze route |
apiDoc |
Future<ApiDoc>? Function()? |
API-documentatie voor Swagger |
widget |
String |
Pad naar een sjabloonbestand dat direct wordt gerenderd, zonder dat er een controller of index nodig is (zie Widget-routes hieronder) |
title |
String |
Paginatitel, beschikbaar in sjablonen als {{ $e.pageTitle }} |
Gebruik per route slechts één van widget, index of controller. Als er meer dan één is ingesteld, wordt eerst widget gecontroleerd, dan index, en ten slotte controller.index() als terugvaloptie.
HTTP-methoden
// Handige constanten van de Methods-klasse:
Methods.ONLY_GET // ['GET']
Methods.ONLY_POST // ['POST']
Methods.ONLY_PUT // ['PUT']
Methods.ONLY_DELETE // ['DELETE']
Methods.GET_POST // ['POST', 'GET']
Methods.ALL // Alle standaard HTTP-methoden
// Of een aangepaste lijst:
methods: [Methods.GET, Methods.POST, Methods.DELETE]
Padparameters
Gebruik de {name}-syntaxis om URL-segmenten vast te leggen. Lees ze in de controller met rq.getParam('name'):
FinchRoute(
key: 'users.show',
path: 'users/{id}', // of 'users/:id'
methods: Methods.ONLY_GET,
index: userController.show,
),
Opmerking: Dynamische padsegmenten kunnen worden gedefinieerd met de syntax {param} of :param. Beide worden ondersteund en functioneren identiek.
// In UserController:
Future<String> show() async {
var id = rq.getParam('id');
return rq.renderData(data: {'id': id});
}
Widget-routes
Wanneer een route alleen een sjabloon moet renderen zonder aangepaste logica, stel dan widget in op een sjabloonpad in plaats van een controller te schrijven:
FinchRoute(
key: 'about',
path: 'about',
title: 'About Us',
widget: 'pages/about',
),
widget wordt gecontroleerd vóór index en controller, en — in tegenstelling tot die twee — wacht het niet totdat de eigen auth van deze route eerst wordt uitgevoerd; alleen permissies die zijn geërfd van een reeds geauthenticeerde bovenliggende route worden gecontroleerd. Als een widget-route zijn eigen authenticatie nodig heeft, koppel dan auth aan een bovenliggende route in plaats van te vertrouwen op het auth-veld van de widget-route zelf, of gebruik index/controller zodat de auth-controle normaal wordt uitgevoerd.
Wildcardpaden en uitsluitingen
Een pad dat eindigt op * komt overeen met de route zelf en elk subpad daaronder — handig voor catch-all handlers zoals een fallback voor een single-page app of een generieke bestandsproxy:
FinchRoute(
key: 'spa.fallback',
path: 'app/*',
index: homeController.spaIndex,
excludePaths: ['app/api'], // valt nog steeds door naar andere routes voor dit subpad
),
excludePaths bevat subpaden die niet door de wildcard mogen worden opgeslokt, zodat specifiekere routes (of statische bestanden) onder de wildcard nog steeds bereikbaar blijven.
Geneste routes (children)
Kindpaden zijn relatief ten opzichte van het bovenliggende pad:
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 paden
extraPath koppelt extra URL-prefixen aan dezelfde route en de bijbehorende kindroutes:
FinchRoute(
key: 'root.mysql',
path: 'example/mysql',
extraPath: ['api/example/mysql'],
methods: Methods.GET_POST,
index: homeController.exampleMysql,
),
Meerdere vergelijkbare routes maken
FinchRoute.makeList maakt meerdere routes aan die dezelfde configuratie delen maar alleen verschillen in pad — handig voor aliassen of bijna identieke endpoints:
var routes = FinchRoute.makeList(
paths: ['users', 'members', 'people'],
methods: Methods.ONLY_GET,
controller: UserController(),
auth: AppAuthController(),
permissions: ['user.read'],
key: 'user.alias', // wordt 'user.alias.1', 'user.alias.2', 'user.alias.3'
);
Middleware
Koppel een of meer Middleware-instanties aan een route (of een vloeiende .middleware()-keten) om verzoekfilterlogica uit te voeren voordat de handler wordt uitgevoerd — logging, headercontroles, rate limiting, CORS en vergelijkbare cross-cutting concerns. Zie de Middleware Guide voor de volledige API en de uitvoeringsvolgorde ten opzichte van auth en permissions.
Host- en poortfiltering
Beperk een route tot specifieke hosts of poorten:
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,
),
Authenticatiebeveiliging
Koppel een AuthController om een route te beveiligen. Als auth() false retourneert, wordt het verzoek afgewezen voordat het de handler bereikt:
FinchRoute(
key: 'admin.panel',
path: 'admin/panel',
auth: AppAuthController(),
permissions: ['admin'],
index: adminController.panel,
),
Zie Auth Controller voor implementatiedetails.
Route-caching
Gebruik de .cache()-extensie om antwoorden te cachen:
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,
),
Zie Route Cache voor volledige details.
URL's genereren vanuit routesleutels
Gebruik in sjablonen $e.routeUrl('key') om URL's te genereren:
<a href="{{ $e.routeUrl('example.panel') }}">Paneel</a>
<a href="{{ $e.routeUrl('users.show', {'id': user.id}) }}">Gebruiker tonen</a>
Alle routes ophalen
Haal de volledige lijst met routes op tijdens runtime:
var routes = await app.getAllRoutes();
Hoe matching werkt
Voor elk binnenkomend verzoek doorloopt Finch de routeringslijst die je hebt geregistreerd met app.addRouting() in volgorde, van boven naar beneden:
- Host/poortfilter — een route wordt direct overgeslagen als
hostsofportsniet overeenkomen met het verzoek. - Padovereenkomst — het
pathvan de route (plus elkeextraPath) wordt vergeleken met het aangevraagde pad, waarbij{param}/:param-placeholders en wildcard*-achtervoegsels onderweg worden opgelost. - Als het pad overeenkomt maar
methodsde HTTP-methode van het verzoek niet bevat, wordt de route behandeld als niet gevonden en gaat de matching verder met de volgende route. - Als de route
childrenheeft, gaat Finch recursief verder zodra het padprefix van de ouder overeenkomt —authenmiddlewaresvan de ouder worden nog steeds eerst uitgevoerd en zijn van toepassing op elk kind. - De eerste route die volledig overeenkomt (pad, methode, host, poort, auth, permissions, middleware) verwerkt het verzoek; er worden geen verdere routes geprobeerd.
- Als niets overeenkomt, valt Finch terug op het serveren van een statisch bestand vanuit
publicDir, en retourneert een404als dat bestand ook niet bestaat.
Omdat de eerste match wint, is de volgorde belangrijk: plaats specifiekere routes vóór bredere wildcardroutes die ze anders zouden kunnen opslokken.