platform/lib/src/http/controller.dart

119 lines
3.7 KiB
Dart
Raw Normal View History

library angel_framework.http.controller;
import 'dart:async';
import 'dart:mirrors';
import 'angel_base.dart';
import 'angel_http_exception.dart';
import 'metadata.dart';
import 'request_context.dart';
import 'response_context.dart';
import 'routable.dart';
import 'route.dart';
2016-06-27 00:20:42 +00:00
class Controller {
AngelBase app;
2016-06-27 00:20:42 +00:00
List middleware = [];
List<Route> routes = [];
Map<String, Route> routeMappings = {};
2016-06-27 00:20:42 +00:00
Expose exposeDecl;
Controller() {
// Load global expose decl
ClassMirror classMirror = reflectClass(this.runtimeType);
for (InstanceMirror metadatum in classMirror.metadata) {
if (metadatum.reflectee is Expose) {
exposeDecl = metadatum.reflectee;
break;
}
}
if (exposeDecl == null)
throw new Exception(
"All controllers must carry an @Expose() declaration.");
else routes.add(
new Route(
"*", "*", []..addAll(exposeDecl.middleware)..addAll(middleware)));
InstanceMirror instanceMirror = reflect(this);
classMirror.instanceMembers.forEach((Symbol key,
MethodMirror methodMirror) {
if (methodMirror.isRegularMethod && key != #toString &&
key != #noSuchMethod && key != #call && key != #equals &&
key != #==) {
InstanceMirror exposeMirror = methodMirror.metadata.firstWhere((
mirror) => mirror.reflectee is Expose, orElse: () => null);
if (exposeMirror != null) {
RequestHandler handler = (RequestContext req,
ResponseContext res) async {
List args = [];
// Load parameters, and execute
for (int i = 0; i < methodMirror.parameters.length; i++) {
ParameterMirror parameter = methodMirror.parameters[i];
if (parameter.type.reflectedType == RequestContext)
args.add(req);
else if (parameter.type.reflectedType == ResponseContext)
args.add(res);
2016-09-17 16:12:25 +00:00
else {String name = MirrorSystem.getName(parameter.simpleName);
var arg = req.params[name];
2016-09-17 16:12:25 +00:00
if (arg == null) {
if (parameter.type.reflectedType != dynamic) {
try {
arg = app.container.make(parameter.type.reflectedType);
if (arg != null) {
args.add(arg);
continue;
}
} catch(e) {
//
}
}
2016-06-27 00:20:42 +00:00
2016-09-17 16:12:25 +00:00
if (!exposeMirror.reflectee.allowNull.contain(name))
throw new AngelHttpException.BadRequest(message: "Missing parameter '$name'");
} else args.add(arg);
}
2016-06-27 00:20:42 +00:00
}
return await instanceMirror
.invoke(key, args)
.reflectee;
2016-06-27 00:20:42 +00:00
};
Route route = new Route(
exposeMirror.reflectee.method,
exposeMirror.reflectee.path,
[]
..addAll(exposeMirror.reflectee.middleware)
..add(handler));
2016-06-27 00:20:42 +00:00
routes.add(route);
String name = exposeMirror.reflectee.as;
if (name == null || name.isEmpty)
name = MirrorSystem.getName(key);
routeMappings[name] = route;
2016-06-27 00:20:42 +00:00
}
}
});
}
Future call(AngelBase app) async {
this.app = app;
app.use(exposeDecl.path, generateRoutable());
TypeMirror typeMirror = reflectType(this.runtimeType);
String name = exposeDecl.as;
if (name == null || name.isEmpty)
name = MirrorSystem.getName(typeMirror.simpleName);
app.controllers[name] = this;
}
Routable generateRoutable() => new Routable()..routes.addAll(routes);
2016-06-27 00:20:42 +00:00
}