Fixed everything

This commit is contained in:
thosakwe 2016-11-23 04:13:42 -05:00
parent 34a234cb4d
commit e06d89a8b1
5 changed files with 121 additions and 58 deletions

View file

@ -6,6 +6,7 @@
<excludeFolder url="file://$MODULE_DIR$/.tmp" /> <excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/packages" /> <excludeFolder url="file://$MODULE_DIR$/packages" />
<excludeFolder url="file://$MODULE_DIR$/temp" /> <excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/test/method/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/packages" /> <excludeFolder url="file://$MODULE_DIR$/test/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/route/packages" /> <excludeFolder url="file://$MODULE_DIR$/test/route/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/router/packages" /> <excludeFolder url="file://$MODULE_DIR$/test/router/packages" />

View file

@ -1,4 +1,8 @@
# angel_route # angel_route
![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev+7-red.svg)
![build status](https://travis-ci.org/angel-dart/route.svg)
A powerful, isomorphic routing library for Dart. A powerful, isomorphic routing library for Dart.
This API is a huge improvement over the original [Angel](https://github.com/angel-dart/angel) This API is a huge improvement over the original [Angel](https://github.com/angel-dart/angel)

View file

@ -177,7 +177,7 @@ class Route {
Route result; Route result;
if (path is RegExp) { if (path is RegExp) {
result = new Route(path, debug: debug); result = new Route(path, debug: debug, handlers: handlers, method: method, name: name);
} else { } else {
final segments = path final segments = path
.toString() .toString()
@ -302,7 +302,7 @@ class Route {
/// Generates a URI to this route with the given parameters. /// Generates a URI to this route with the given parameters.
String makeUri([Map<String, dynamic> params]) { String makeUri([Map<String, dynamic> params]) {
String result = _pathified; String result = _pathify(path);
if (params != null) { if (params != null) {
for (String key in (params.keys)) { for (String key in (params.keys)) {
result = result.replaceAll( result = result.replaceAll(
@ -323,8 +323,14 @@ class Route {
Iterable<String> values = Iterable<String> values =
_parseParameters(requestPath.replaceAll(_straySlashes, '')); _parseParameters(requestPath.replaceAll(_straySlashes, ''));
_printDebug('Searched request path $requestPath and found these values: $values');
final pathString = _pathify(path).replaceAll(new RegExp('\/'), r'\/');
Iterable<Match> matches = Iterable<Match> matches =
_param.allMatches(_pathified.replaceAll(new RegExp('\/'), r'\/')); _param.allMatches(pathString);
_printDebug('All param names parsed in $pathString: ${matches.map((m) => m.group(0))}');
for (int i = 0; i < matches.length && i < values.length; i++) { for (int i = 0; i < matches.length && i < values.length; i++) {
Match match = matches.elementAt(i); Match match = matches.elementAt(i);
String paramName = match.group(1); String paramName = match.group(1);

View file

@ -8,7 +8,8 @@ part 'route.dart';
final RegExp _param = new RegExp(r':([A-Za-z0-9_]+)(\((.+)\))?'); final RegExp _param = new RegExp(r':([A-Za-z0-9_]+)(\((.+)\))?');
final RegExp _rgxEnd = new RegExp(r'\$+$'); final RegExp _rgxEnd = new RegExp(r'\$+$');
final RegExp _rgxStart = new RegExp(r'^\^+'); final RegExp _rgxStart = new RegExp(r'^\^+');
final RegExp _rgxStraySlashes = new RegExp(r'(^((\\/)|(/))+)|(((\\/)|(/))+$)'); final RegExp _rgxStraySlashes =
new RegExp(r'(^((\\+/)|(/))+)|(((\\+/)|(/))+$)');
final RegExp _slashDollar = new RegExp(r'/+\$'); final RegExp _slashDollar = new RegExp(r'/+\$');
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
@ -28,8 +29,7 @@ class Router extends Extensible {
/// Provide a `root` to make this Router revolve around a pre-defined route. /// Provide a `root` to make this Router revolve around a pre-defined route.
/// Not recommended. /// Not recommended.
Router({this.debug: false, Route root}) { Router({this.debug: false, Route root}) {
_root = (_root = root ?? new _RootRoute()) _root = (_root = root ?? new _RootRoute())..debug = debug;
..debug = debug;
} }
void _printDebug(msg) { void _printDebug(msg) {
@ -49,13 +49,12 @@ class Router extends Extensible {
if (path is RegExp) { if (path is RegExp) {
return root.child(path, debug: debug, handlers: handlers, method: method); return root.child(path, debug: debug, handlers: handlers, method: method);
} else if (path } else {
.toString() // if (path.toString().replaceAll(_straySlashes, '').isEmpty || true) {
.replaceAll(_straySlashes, '')
.isEmpty) {
return root.child(path.toString(), return root.child(path.toString(),
debug: debug, handlers: handlers, method: method); debug: debug, handlers: handlers, method: method);
} else { }
/* else {
var segments = path var segments = path
.toString() .toString()
.split('/') .split('/')
@ -80,7 +79,7 @@ class Router extends Extensible {
do { do {
existing = result.resolve(segments[0], existing = result.resolve(segments[0],
filter: (route) => filter: (route) =>
route.method == method || route.method == '*'); route.method == method || route.method == '*');
if (existing != null) { if (existing != null) {
result = existing; result = existing;
@ -111,19 +110,21 @@ class Router extends Extensible {
} }
return result..debug = debug; return result..debug = debug;
} } */
} }
/// Creates a visual representation of the route hierarchy and /// Creates a visual representation of the route hierarchy and
/// passes it to a callback. If none is provided, `print` is called. /// passes it to a callback. If none is provided, `print` is called.
void dumpTree( void dumpTree(
{callback(String tree), header: 'Dumping route tree:', tab: ' '}) { {callback(String tree),
header: 'Dumping route tree:',
tab: ' ',
showMatchers: false}) {
var tabs = 0; var tabs = 0;
final buf = new StringBuffer(); final buf = new StringBuffer();
void dumpRoute(Route route, {Pattern replace: null}) { void dumpRoute(Route route, {Pattern replace: null}) {
for (var i = 0; i < tabs; i++) for (var i = 0; i < tabs; i++) buf.write(tab);
buf.write(tab);
if (route == root) if (route == root)
buf.writeln('(root)'); buf.writeln('(root)');
@ -131,7 +132,7 @@ class Router extends Extensible {
buf.write('- ${route.method} '); buf.write('- ${route.method} ');
var p = var p =
replace != null ? route.path.replaceAll(replace, '') : route.path; replace != null ? route.path.replaceAll(replace, '') : route.path;
p = p.replaceAll(_straySlashes, ''); p = p.replaceAll(_straySlashes, '');
if (p.isEmpty) if (p.isEmpty)
@ -139,6 +140,10 @@ class Router extends Extensible {
else else
buf.write("'${p.replaceAll(_straySlashes, '')}'"); buf.write("'${p.replaceAll(_straySlashes, '')}'");
if (showMatchers) {
buf.write(' (matcher: ${route.matcher.pattern})');
}
if (route.handlers.isNotEmpty) if (route.handlers.isNotEmpty)
buf.writeln(' => ${route.handlers.length} handler(s)'); buf.writeln(' => ${route.handlers.length} handler(s)');
else else
@ -168,7 +173,7 @@ class Router extends Extensible {
String name: null, String name: null,
String namespace: null}) { String namespace: null}) {
final route = final route =
root.child(path, handlers: middleware, method: method, name: name); root.child(path, handlers: middleware, method: method, name: name);
final router = new Router(root: route); final router = new Router(root: route);
callback(router); callback(router);
@ -178,7 +183,7 @@ class Router extends Extensible {
Map copiedMiddleware = new Map.from(router.requestMiddleware); Map copiedMiddleware = new Map.from(router.requestMiddleware);
for (String middlewareName in copiedMiddleware.keys) { for (String middlewareName in copiedMiddleware.keys) {
requestMiddleware["$middlewarePrefix$middlewareName"] = requestMiddleware["$middlewarePrefix$middlewareName"] =
copiedMiddleware[middlewareName]; copiedMiddleware[middlewareName];
} }
return route; return route;
@ -211,8 +216,7 @@ class Router extends Extensible {
_resolve(Route ref, String fullPath, String method, String head, _resolve(Route ref, String fullPath, String method, String head,
Iterable<String> tail) { Iterable<String> tail) {
_printDebug( _printDebug('$method $fullPath on $ref: head: $head, tail: ${tail.join(
'$method on $ref: path: $fullPath, head: $head, tail: ${tail.join(
'/')}'); '/')}');
// Does the index route match? // Does the index route match?
@ -240,19 +244,9 @@ class Router extends Extensible {
return index; return index;
} }
} else { } else {
// Try to match children by full path
for (Route child in ref.children) {
if (child.matcher.hasMatch(fullPath)) {
final resolved = _resolve(child, fullPath, method, head, tail);
if (resolved != null) {
return resolved;
}
}
}
// Now, let's check if any route's head matches the // Now, let's check if any route's head matches the
// given head. If so, we try to resolve with that // given head. If so, we try to resolve with that
// given head. If so, we try to resolve with that
// route, using a head corresponding to the one we // route, using a head corresponding to the one we
// matched. // matched.
for (Route child in ref.children) { for (Route child in ref.children) {
@ -277,8 +271,21 @@ class Router extends Extensible {
} }
} else if (child._head != null) { } else if (child._head != null) {
_printDebug( _printDebug(
'Head ${child._head 'Head ${child._head.pattern} on $child failed to match $fullPath');
.pattern} on $child failed to match $fullPath'); }
}
// Try to match children by full path
for (Route child in ref.children) {
if (child.matcher.hasMatch(fullPath)) {
final resolved = _resolve(child, fullPath, method, head, tail);
if (resolved != null) {
return resolved;
}
} else {
_printDebug(
'Could not match full path $fullPath to matcher ${child.matcher.pattern}.');
} }
} }
} }
@ -291,12 +298,12 @@ class Router extends Extensible {
} }
} }
/// Returns a new Router in which the route tree has been /// Flattens the route tree into a linear list.
/// flattened into a linear list. void flatten() {
Router flatten() { final router = new Router(debug: debug);
final router = new Router(); normalize();
_flatten(Route route) { _flatten(Route parent, Route route) {
// if (route.children.isNotEmpty && route.method == '*') return; // if (route.children.isNotEmpty && route.method == '*') return;
final r = new Route._base(); final r = new Route._base();
@ -306,15 +313,34 @@ class Router extends Extensible {
.._head = route._head .._head = route._head
.._matcher = route.matcher .._matcher = route.matcher
.._method = route.method .._method = route.method
.._parent = router.root .._name = route.name
.._path = route.path; .._parent = route.parent // router.root
.._path = route
.path; //'${parent.path}/${route.path}'.replaceAll(_straySlashes, '');
// New matcher
final part1 = parent.matcher.pattern
.replaceAll(_rgxStart, '')
.replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, '')
.replaceAll(_straySlashes, '');
final part2 = route.matcher.pattern
.replaceAll(_rgxStart, '')
.replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, '')
.replaceAll(_straySlashes, '');
final m = '$part1\\/$part2'.replaceAll(_rgxStraySlashes, '');
// r._matcher = new RegExp('^$m\$');
_printDebug('Matcher of flattened route: ${r.matcher.pattern}');
router.root._children.add(r); router.root._children.add(r);
route.children.forEach(_flatten); route.children.forEach((child) => _flatten(route, child));
} }
root._children.forEach(_flatten); root._children.forEach((child) => _flatten(root, child));
return router..debug = debug; _root = router.root;
} }
/// Incorporates another [Router]'s routes into this one's. /// Incorporates another [Router]'s routes into this one's.
@ -335,7 +361,7 @@ class Router extends Extensible {
Map copiedMiddleware = new Map.from(router.requestMiddleware); Map copiedMiddleware = new Map.from(router.requestMiddleware);
for (String middlewareName in copiedMiddleware.keys) { for (String middlewareName in copiedMiddleware.keys) {
requestMiddleware["$middlewarePrefix$middlewareName"] = requestMiddleware["$middlewarePrefix$middlewareName"] =
copiedMiddleware[middlewareName]; copiedMiddleware[middlewareName];
} }
// final route = root.addChild(router.root, join: false); // final route = root.addChild(router.root, join: false);
@ -343,17 +369,36 @@ class Router extends Extensible {
route.debug = debug; route.debug = debug;
if (path is! RegExp) { if (path is! RegExp) {
// Correct mounted path manually...
final clean = route.matcher.pattern
.replaceAll(_rgxStart, '')
.replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, '');
route._matcher = new RegExp('^$clean\$');
final _path = path.toString().replaceAll(_straySlashes, ''); final _path = path.toString().replaceAll(_straySlashes, '');
_migrateRoute(Route r) { _migrateRoute(Route r) {
r._path = '$_path/${r.path}'.replaceAll(_straySlashes, ''); r._path = '$_path/${r.path}'.replaceAll(_straySlashes, '');
var stripped = r.matcher.pattern var m = r.matcher.pattern
.replaceAll(_rgxStart, '') .replaceAll(_rgxStart, '')
.replaceAll(_rgxEnd, '') .replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, '') .replaceAll(_rgxStraySlashes, '')
.replaceAll(_straySlashes, ''); .replaceAll(_straySlashes, '');
stripped = '$_path/$stripped'.replaceAll(_straySlashes, '');
r._matcher = new RegExp('^$stripped\$'); final m1 = _matcherify(_path)
.replaceAll(_rgxStart, '')
.replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, '')
.replaceAll(_straySlashes, '');
m = '$m1/$m'
.replaceAll(_rgxStraySlashes, '')
.replaceAll(_straySlashes, '');
r._matcher = new RegExp('^$m\$');
_printDebug(
'New matcher on route in mounted router: ${r.matcher.pattern}');
if (r._head != null) { if (r._head != null) {
final head = r._head.pattern final head = r._head.pattern
@ -362,7 +407,9 @@ class Router extends Extensible {
.replaceAll(_rgxStraySlashes, '') .replaceAll(_rgxStraySlashes, '')
.replaceAll('\\/', '/') .replaceAll('\\/', '/')
.replaceAll(_straySlashes, ''); .replaceAll(_straySlashes, '');
r._head = new RegExp(_matcherify('$_path/$head').replaceAll(_rgxEnd, '')); r._head = new RegExp(_matcherify('$_path/$head')
.replaceAll(_rgxEnd, '')
.replaceAll(_rgxStraySlashes, ''));
_printDebug('Head of migrated route: ${r._head.pattern}'); _printDebug('Head of migrated route: ${r._head.pattern}');
} }
@ -377,25 +424,30 @@ class Router extends Extensible {
void normalize() { void normalize() {
_printDebug('Normalizing route tree...'); _printDebug('Normalizing route tree...');
_normalize(Route route) { _normalize(Route route, int index) {
route.children.forEach(_normalize); var merge = route.path.replaceAll(_straySlashes, '').isEmpty &&
route.children.isNotEmpty;
merge = merge || route.children.length == 1;
if (route.path if (merge) {
.replaceAll(_straySlashes, '')
.isEmpty &&
route.children.isNotEmpty) {
_printDebug('Erasing this route: $route'); _printDebug('Erasing this route: $route');
route.parent._handlers.addAll(route.handlers); route.parent._handlers.addAll(route.handlers);
for (Route child in route.children) { for (Route child in route.children) {
route.parent._children.add(child.._parent = route.parent); route.parent._children.insert(index, child.._parent = route.parent);
} }
route.parent._children.remove(route); route.parent._children.remove(route);
} }
for (int i = 0; i < route.children.length; i++) {
_normalize(route.children[i], i);
}
} }
root.children.forEach(_normalize); for (int i = 0; i < root.children.length; i++) {
_normalize(root.children[i], i);
}
} }
/// Adds a route that responds to any request matching the given path. /// Adds a route that responds to any request matching the given path.

View file

@ -1,6 +1,6 @@
name: angel_route name: angel_route
description: A powerful, isomorphic routing library for Dart. description: A powerful, isomorphic routing library for Dart.
version: 1.0.0-dev+6 version: 1.0.0-dev+7
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_route homepage: https://github.com/angel-dart/angel_route
dev_dependencies: dev_dependencies: