Fixed everything
This commit is contained in:
parent
34a234cb4d
commit
e06d89a8b1
5 changed files with 121 additions and 58 deletions
|
@ -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" />
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue