Router: allow to mount a Handler (#86)
* Router: allow to mount a handler
And make Router to be a Handler
* Deprecate the handler getter of Router
* Add a changelog entry and bump version
diff --git a/pkgs/shelf_router/CHANGELOG.md b/pkgs/shelf_router/CHANGELOG.md
index f3e0569..0c63df2 100644
--- a/pkgs/shelf_router/CHANGELOG.md
+++ b/pkgs/shelf_router/CHANGELOG.md
@@ -1,3 +1,9 @@
+## v0.7.4
+
+ * Update `Router.mount` parameter to accept a `Handler`.
+ * Make `Router` to be considered a `Handler`.
+ * Deprecate the `Router.handler` getter.
+
## v0.7.3
* Added `@sealed` annotation to `Router` and `Route`.
diff --git a/pkgs/shelf_router/example/main.dart b/pkgs/shelf_router/example/main.dart
index e95344d..ebd7dfd 100644
--- a/pkgs/shelf_router/example/main.dart
+++ b/pkgs/shelf_router/example/main.dart
@@ -52,7 +52,7 @@
return Response.notFound('Page not found');
});
- return router.handler;
+ return router;
}
}
diff --git a/pkgs/shelf_router/lib/src/router.dart b/pkgs/shelf_router/lib/src/router.dart
index a3102cd..ba086d3 100644
--- a/pkgs/shelf_router/lib/src/router.dart
+++ b/pkgs/shelf_router/lib/src/router.dart
@@ -115,18 +115,17 @@
_routes.add(RouterEntry('ALL', route, handler));
}
- /// Mount a router below a prefix.
+ /// Mount a handler below a prefix.
///
/// In this case prefix may not contain any parameters, nor
- void mount(String prefix, Router router) {
+ void mount(String prefix, Handler handler) {
ArgumentError.checkNotNull(prefix, 'prefix');
- ArgumentError.checkNotNull(router, 'router');
+ ArgumentError.checkNotNull(handler, 'handler');
if (!prefix.startsWith('/') || !prefix.endsWith('/')) {
throw ArgumentError.value(
prefix, 'prefix', 'must start and end with a slash');
}
- final handler = router.handler;
// first slash is always in request.handlerPath
final path = prefix.substring(1);
all(prefix + '<path|[^]*>', (Request request) {
@@ -135,24 +134,28 @@
}
/// Get a [Handler] that will route incoming requests to registered handlers.
- Handler get handler {
+ @Deprecated('The Router class is a Handler on its own')
+ Handler get handler => call;
+
+ /// Route incoming requests to registered handlers.
+ ///
+ /// This method allows a Router instance to be a [Handler].
+ Future<Response> call(Request request) async {
// Note: this is a great place to optimize the implementation by building
// a trie for faster matching... left as an exercise for the reader :)
- return (Request request) async {
- for (var route in _routes) {
- if (route.verb != request.method.toUpperCase() && route.verb != 'ALL') {
- continue;
- }
- var params = route.match('/' + request.url.path);
- if (params != null) {
- var res = await route.invoke(request, params);
- if (res != null) {
- return res;
- }
+ for (var route in _routes) {
+ if (route.verb != request.method.toUpperCase() && route.verb != 'ALL') {
+ continue;
+ }
+ var params = route.match('/' + request.url.path);
+ if (params != null) {
+ var res = await route.invoke(request, params);
+ if (res != null) {
+ return res;
}
}
- return null;
- };
+ }
+ return null;
}
// Handlers for all methods
diff --git a/pkgs/shelf_router/pubspec.yaml b/pkgs/shelf_router/pubspec.yaml
index c0befeb..394d5c7 100644
--- a/pkgs/shelf_router/pubspec.yaml
+++ b/pkgs/shelf_router/pubspec.yaml
@@ -1,5 +1,5 @@
name: shelf_router
-version: 0.7.3
+version: 0.7.4
description: |
A convinent request router for the shelf web-framework, with support for
URL-parameters, nested routers and routers generated from source annotations.
diff --git a/pkgs/shelf_router/test/router_test.dart b/pkgs/shelf_router/test/router_test.dart
index 5eeae1b..3f33d91 100644
--- a/pkgs/shelf_router/test/router_test.dart
+++ b/pkgs/shelf_router/test/router_test.dart
@@ -60,7 +60,7 @@
return Response.ok('not-found');
});
- server.mount(app.handler);
+ server.mount(app);
expect(await get('/sync-hello'), 'hello-world');
expect(await get('/async-hello'), 'hello-world');
@@ -80,7 +80,7 @@
return Response.ok('$user / $group');
});
- server.mount(app.handler);
+ server.mount(app);
expect(await get('/user/jonasfj/groups/42'), 'jonasfj / 42');
});
@@ -93,7 +93,7 @@
return Response.ok('$user / $group');
});
- server.mount(app.handler);
+ server.mount(app);
expect(await get('/user/jonasfj/groups/42'), 'jonasfj / 42');
});
@@ -115,10 +115,37 @@
return Response.notFound('catch-all-handler');
});
- server.mount(app.handler);
+ server.mount(app);
expect(await get('/hello'), 'hello-world');
expect(await get('/api/user/jonasfj/info'), 'Hello jonasfj');
expect(get('/api/user/jonasfj/info-wrong'), throwsA(anything));
});
+
+ test('mount(Handler) with middleware', () async {
+ var api = Router();
+ api.get('/hello', (Request request) {
+ return Response.ok('Hello');
+ });
+
+ final middleware = createMiddleware(
+ requestHandler: (request) {
+ if (request.url.queryParameters.containsKey('ok')) {
+ return Response.ok('middleware');
+ }
+ return null;
+ },
+ );
+
+ var app = Router();
+ app.mount(
+ '/api/',
+ Pipeline().addMiddleware(middleware).addHandler(api),
+ );
+
+ server.mount(app);
+
+ expect(await get('/api/hello'), 'Hello');
+ expect(await get('/api/hello?ok'), 'middleware');
+ });
}