Merge branch 'master' into experimental

This commit is contained in:
Tobe O 2019-10-12 10:04:13 -04:00
commit 564310baca
6 changed files with 36 additions and 10 deletions

View file

@ -6,6 +6,10 @@
* Default to using `ThrowingReflector`, instead of `EmptyReflector`. This will give a more descriptive
error when trying to use controllers, etc. without reflection enabled.
# 2.0.4+1
* Run `Controller.configureRoutes` before mounting `@Expose` routes.
* Make `Controller.configureServer` always return a `Future`.
# 2.0.4
* Prepare for Dart SDK change to `Stream<List<int>>` that are now
`Stream<Uint8List>`.

View file

@ -27,7 +27,7 @@ class Controller {
/// Applies routes, DI, and other configuration to an [app].
@mustCallSuper
FutureOr<void> configureServer(Angel app) {
Future<void> configureServer(Angel app) async {
_app = app;
if (injectSingleton != false) {
@ -36,13 +36,13 @@ class Controller {
}
}
var name = applyRoutes(app, app.container.reflector);
var name = await applyRoutes(app, app.container.reflector);
app.controllers[name] = this;
return null;
}
/// Applies the routes from this [Controller] to some [router].
String applyRoutes(Router router, Reflector reflector) {
Future<String> applyRoutes(Router router, Reflector reflector) async {
// Load global expose decl
var classMirror = reflector.reflectClass(this.runtimeType);
Expose exposeDecl = findExpose(reflector);
@ -62,8 +62,8 @@ class Controller {
..addAll(middleware);
final routeBuilder =
_routeBuilder(reflector, instanceMirror, routable, handlers);
await configureRoutes(routable);
classMirror.declarations.forEach(routeBuilder);
configureRoutes(routable);
// Return the name.
return exposeDecl.as?.isNotEmpty == true ? exposeDecl.as : typeMirror.name;
@ -178,8 +178,16 @@ class Controller {
};
}
/// Used to add additional routes to the router from within a [Controller].
void configureRoutes(Routable routable) {}
/// Used to add additional routes or middlewares to the router from within
/// a [Controller].
///
/// ```dart
/// @override
/// FutureOr<void> configureRoutes(Routable routable) {
/// routable.all('*', myMiddleware);
/// }
/// ```
FutureOr<void> configureRoutes(Routable routable) {}
static final RegExp _methods = RegExp(r'^(get|post|patch|delete)');
static final RegExp _multiScore = RegExp(r'__+');

View file

@ -28,7 +28,21 @@ class NoExpose {
const NoExpose noExpose = NoExpose();
/// Exposes a [Controller] or method to the Internet.
/// Exposes a [Controller] or a [Controller] method to the Internet.
/// Example:
///
/// ```dart
/// @Expose('/elements')
/// class ElementController extends Controller {
///
/// @Expose('/')
/// List<Element> getList() => someComputationHere();
///
/// @Expose('/int:elementId')
/// getElement(int elementId) => someOtherComputation();
///
/// }
/// ```
class Expose {
final String method;
final String path;

View file

@ -61,7 +61,7 @@ abstract class ResponseContext<RawResponse>
/// Serializes response data into a String.
///
/// The default is conversion into JSON via `package:json_god`.
/// The default is conversion into JSON via `json.encode`.
///
/// If you are 100% sure that your response handlers will only
/// be JSON-encodable objects (i.e. primitives, `List`s and `Map`s),

View file

@ -113,7 +113,7 @@ main() {
}, optional: ['bar']));
var rq = MockHttpRequest('GET', Uri(path: 'foo'));
await AngelHttp(app).handleRequest(rq);
var body = await rq.response.transform(utf8.decoder).join();
var body = await utf8.decoder.bind(rq.response).join();
expect(json.decode(body), 2);
});

View file

@ -28,7 +28,7 @@ main() {
app.container.registerSingleton(Todo(text: TEXT, over: OVER));
app.container.registerFactory<Future<Foo>>((container) async {
var req = container.make<RequestContext>();
var text = await req.body.transform(utf8.decoder).join();
var text = await utf8.decoder.bind(req.body).join();
return Foo(text);
});