Dart Documentationclean_router.commonRoute

Route class

Maps Map of variables to String Url component and vice versa.

class Route {
 RegExp _matchExp;
 String _absolutePart = '';
 List<String> _variables = [];
 List _urlParts = [];
 bool _anyTail = false;

 get isAbsolute => _absolutePart.isNotEmpty;

 /**
  * Constructs [Route] using [String] pattern.
  *
  * Url is dividid into absolute and patter part.
  * Pattern is divided to parts by slash '/' character. The slash must be the
  * very first character of the pattern. Each part can be either static or
  * placeholder. Static part can contain arbitrary number of [a-zA-Z0-9_-]
  * characters. Placeholder part consists of variable name enclosed in curly
  * braces. Variable name consists of any characters expect curly braces
  * with the first character being not an underscore.
  */

 Route(String url) {
   String pattern;
   if(url.startsWith(new RegExp(r'^(ht|f)tp(s?)://'))) {
     int endOfAbsolutePart = url.indexOf('/', url.indexOf('://') + 3);
     if(endOfAbsolutePart == -1) {
       throw new FormatException('Absolute Url pattern has to have pattern part');
     }
     _absolutePart = url.substring(0, endOfAbsolutePart);
     pattern = url.substring(endOfAbsolutePart);
   }
   else {
     pattern = url;
   }

   if (pattern.isEmpty || pattern[0] != '/') {
     throw new FormatException("Url pattern has to begin with '/' character.");
   }
   if(pattern[pattern.length - 1] == '*'){
     _anyTail = true;
     pattern = pattern.substring(0, pattern.length - 1);
   }

   RegExp exp = new RegExp(r"^(?:([\w-.]*)|{([^_{}][^{}]*)})$");

   var matcherParts = new List();
   var parts = pattern.split('/');
   for (var part in parts) {
     var match = exp.firstMatch(part);
     if (match == null) {
       throw new FormatException(
           """Only alphanumeric characters, dash '-' and underscore '_'
            are allowed in the URL."""
       );
     }
     if (match.group(1) != null) {
       var group = match.group(1);
       matcherParts.add(group);
       _urlParts.add({'value': group, 'isVariable': false});
     } else {
       var group = match.group(2);
       matcherParts.add("([^/]*)");
       _variables.add(group);
       _urlParts.add({'value': group, 'isVariable': true});
     }
   }

   var tailRegExp = r"";
   if(_anyTail){
     tailRegExp = r"(.*)";
   }

   _matchExp = new RegExp(r"^" + _absolutePart + matcherParts.join('/') + tailRegExp + r"$");
 }

 /**
  * Matches the [url] against the [Route] pattern and returns [Map] of matched.
  * This is the inverse function to [Route.path].
  */
 Map match(String url) {
   var match = _matchExp.firstMatch(url);

   // If the [url] does not match, returns [null].
   if (match == null) {
     return null;
   }

   // Decode [url] parameters and fill them into [Map].
   Map result = new Map();
   for (var i = 0; i < _variables.length; i++) {
     result[_variables[i]] = Uri.decodeComponent(match.group(i + 1));
   }

   //Matched url after prefix
   if(_anyTail){
     result[PARAM_TAIL] = Uri.decodeComponent(match.group(_variables.length + 1));
   }

   return result;
 }

 /**
  * Constructs the [url] using the [Route] pattern and values in [variables].
  * This is theiInverse function to [Route.match].
  * Accepts both [Map] as parameters.
  * All [args] of [Route] must be provided.
  */
 String path(Map args) {
   var parts = [];
   for (var part in this._urlParts) {
     var value = part['value'];
     if (part['isVariable']) {
       value = args[value];
       if (value == null) {
         throw new ArgumentError("Missing value for ${part['value']}.");
       }
     }
     parts.add(Uri.encodeComponent(value));
   }
   if (_anyTail) {
     parts.removeLast();
     parts.add(args[PARAM_TAIL]);
   }
   return _absolutePart + parts.join('/');
 }
}

Constructors

new Route(String url) #

Constructs Route using String pattern.

Url is dividid into absolute and patter part. Pattern is divided to parts by slash '/' character. The slash must be the very first character of the pattern. Each part can be either static or placeholder. Static part can contain arbitrary number of a-zA-Z0-9_- characters. Placeholder part consists of variable name enclosed in curly braces. Variable name consists of any characters expect curly braces with the first character being not an underscore.

Route(String url) {
 String pattern;
 if(url.startsWith(new RegExp(r'^(ht|f)tp(s?)://'))) {
   int endOfAbsolutePart = url.indexOf('/', url.indexOf('://') + 3);
   if(endOfAbsolutePart == -1) {
     throw new FormatException('Absolute Url pattern has to have pattern part');
   }
   _absolutePart = url.substring(0, endOfAbsolutePart);
   pattern = url.substring(endOfAbsolutePart);
 }
 else {
   pattern = url;
 }

 if (pattern.isEmpty || pattern[0] != '/') {
   throw new FormatException("Url pattern has to begin with '/' character.");
 }
 if(pattern[pattern.length - 1] == '*'){
   _anyTail = true;
   pattern = pattern.substring(0, pattern.length - 1);
 }

 RegExp exp = new RegExp(r"^(?:([\w-.]*)|{([^_{}][^{}]*)})$");

 var matcherParts = new List();
 var parts = pattern.split('/');
 for (var part in parts) {
   var match = exp.firstMatch(part);
   if (match == null) {
     throw new FormatException(
         """Only alphanumeric characters, dash '-' and underscore '_'
          are allowed in the URL."""
     );
   }
   if (match.group(1) != null) {
     var group = match.group(1);
     matcherParts.add(group);
     _urlParts.add({'value': group, 'isVariable': false});
   } else {
     var group = match.group(2);
     matcherParts.add("([^/]*)");
     _variables.add(group);
     _urlParts.add({'value': group, 'isVariable': true});
   }
 }

 var tailRegExp = r"";
 if(_anyTail){
   tailRegExp = r"(.*)";
 }

 _matchExp = new RegExp(r"^" + _absolutePart + matcherParts.join('/') + tailRegExp + r"$");
}

Properties

final isAbsolute #

get isAbsolute => _absolutePart.isNotEmpty;

Methods

Map match(String url) #

Matches the url against the Route pattern and returns Map of matched. This is the inverse function to Route.path.

Map match(String url) {
 var match = _matchExp.firstMatch(url);

 // If the [url] does not match, returns [null].
 if (match == null) {
   return null;
 }

 // Decode [url] parameters and fill them into [Map].
 Map result = new Map();
 for (var i = 0; i < _variables.length; i++) {
   result[_variables[i]] = Uri.decodeComponent(match.group(i + 1));
 }

 //Matched url after prefix
 if(_anyTail){
   result[PARAM_TAIL] = Uri.decodeComponent(match.group(_variables.length + 1));
 }

 return result;
}

String path(Map args) #

Constructs the url using the Route pattern and values in variables. This is theiInverse function to Route.match. Accepts both Map as parameters. All args of Route must be provided.

String path(Map args) {
 var parts = [];
 for (var part in this._urlParts) {
   var value = part['value'];
   if (part['isVariable']) {
     value = args[value];
     if (value == null) {
       throw new ArgumentError("Missing value for ${part['value']}.");
     }
   }
   parts.add(Uri.encodeComponent(value));
 }
 if (_anyTail) {
   parts.removeLast();
   parts.add(args[PARAM_TAIL]);
 }
 return _absolutePart + parts.join('/');
}