// Copyright 2021, the Flutter project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:flutter/widgets.dart'; import 'package:path_to_regexp/path_to_regexp.dart'; import 'parsed_route.dart'; /// Used by [TemplateRouteParser] to guard access to routes. typedef RouteGuard = Future Function(T from); /// Parses the URI path into a [ParsedRoute]. class TemplateRouteParser extends RouteInformationParser { final List _pathTemplates; final RouteGuard? guard; final ParsedRoute initialRoute; TemplateRouteParser({ /// The list of allowed path templates (['/', '/users/:id']) required List allowedPaths, /// The initial route String initialRoute = '/', /// [RouteGuard] used to redirect. this.guard, }) : initialRoute = ParsedRoute(initialRoute, initialRoute, {}, {}), _pathTemplates = [ ...allowedPaths, ], assert(allowedPaths.contains(initialRoute)); @override Future parseRouteInformation( RouteInformation routeInformation, ) async { final path = routeInformation.location!; final queryParams = Uri.parse(path).queryParameters; var parsedRoute = initialRoute; for (var pathTemplate in _pathTemplates) { final parameters = []; var pathRegExp = pathToRegExp(pathTemplate, parameters: parameters); if (pathRegExp.hasMatch(path)) { final match = pathRegExp.matchAsPrefix(path); if (match == null) continue; final params = extract(parameters, match); parsedRoute = ParsedRoute(path, pathTemplate, params, queryParams); } } // Redirect if a guard is present var guard = this.guard; if (guard != null) { return guard(parsedRoute); } return parsedRoute; } @override RouteInformation restoreRouteInformation(ParsedRoute configuration) => RouteInformation(location: configuration.path); }