platform/lib/src/http/controller.dart

140 lines
4.3 KiB
Dart
Raw Normal View History

library angel_framework.http.controller;
import 'dart:async';
import 'dart:mirrors';
2016-10-22 20:41:36 +00:00
import 'package:angel_route/angel_route.dart';
import 'angel_base.dart';
import 'angel_http_exception.dart';
import 'metadata.dart';
import 'request_context.dart';
import 'response_context.dart';
import 'routable.dart';
2016-06-27 00:20:42 +00:00
class Controller {
AngelBase app;
2016-06-27 00:20:42 +00:00
List middleware = [];
Map<String, Route> routeMappings = {};
2016-06-27 00:20:42 +00:00
Expose exposeDecl;
2016-10-22 20:41:36 +00:00
Future call(AngelBase app) async {
this.app = app;
2016-06-27 00:20:42 +00:00
// Load global expose decl
ClassMirror classMirror = reflectClass(this.runtimeType);
for (InstanceMirror metadatum in classMirror.metadata) {
if (metadatum.reflectee is Expose) {
exposeDecl = metadatum.reflectee;
break;
}
}
2016-10-22 20:41:36 +00:00
if (exposeDecl == null) {
2016-06-27 00:20:42 +00:00
throw new Exception(
"All controllers must carry an @Expose() declaration.");
2016-10-22 20:41:36 +00:00
}
2016-11-28 21:48:00 +00:00
final routable = new Routable(debug: true);
configureRoutes(routable);
app.use(exposeDecl.path, routable);
2016-11-23 09:10:47 +00:00
TypeMirror typeMirror = reflectType(this.runtimeType);
String name = exposeDecl.as;
2016-06-27 00:20:42 +00:00
2016-11-23 09:10:47 +00:00
if (name == null || name.isEmpty)
name = MirrorSystem.getName(typeMirror.simpleName);
app.controllers[name] = this;
}
_callback(InstanceMirror instanceMirror, Routable routable, List handlers) {
return (Symbol key, MethodMirror methodMirror) {
2016-10-22 20:41:36 +00:00
if (methodMirror.isRegularMethod &&
key != #toString &&
key != #noSuchMethod &&
key != #call &&
key != #equals &&
2016-06-27 00:20:42 +00:00
key != #==) {
2016-10-22 20:41:36 +00:00
InstanceMirror exposeMirror = methodMirror.metadata.firstWhere(
(mirror) => mirror.reflectee is Expose,
orElse: () => null);
2016-06-27 00:20:42 +00:00
if (exposeMirror != null) {
2016-10-22 20:41:36 +00:00
RequestHandler handler =
(RequestContext req, ResponseContext res) async {
2016-06-27 00:20:42 +00:00
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-10-22 20:41:36 +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) {
2016-11-23 19:50:17 +00:00
if (req.injections.containsKey(name)) {
args.add(req.injections[name]);
continue;
}
final type = parameter.type.reflectedType;
if (req.injections.containsKey(type)) {
args.add(req.injections[type]);
continue;
}
if (type != dynamic) {
2016-09-17 16:12:25 +00:00
try {
2016-11-23 19:50:17 +00:00
args.add(app.container.make(type));
continue;
2016-10-22 20:41:36 +00:00
} catch (e) {
2016-09-17 16:12:25 +00:00
//
2016-11-23 19:50:17 +00:00
print(e);
print(req.injections);
2016-09-17 16:12:25 +00:00
}
}
2016-06-27 00:20:42 +00:00
2016-11-23 19:50:17 +00:00
if (!exposeMirror.reflectee.allowNull.contains(name))
2016-10-22 20:41:36 +00:00
throw new AngelHttpException.BadRequest(
message: "Missing parameter '$name'");
} else
args.add(arg);
}
2016-06-27 00:20:42 +00:00
}
2016-10-22 20:41:36 +00:00
return await instanceMirror.invoke(key, args).reflectee;
2016-06-27 00:20:42 +00:00
};
2016-10-22 20:41:36 +00:00
2016-11-23 09:10:47 +00:00
final middleware = []
..addAll(handlers)
..addAll(exposeMirror.reflectee.middleware);
2016-10-22 20:41:36 +00:00
final route = routable.addRoute(exposeMirror.reflectee.method,
exposeMirror.reflectee.path, handler,
2016-11-23 09:10:47 +00:00
middleware: middleware);
2016-06-27 00:20:42 +00:00
String name = exposeMirror.reflectee.as;
2016-10-22 20:41:36 +00:00
if (name == null || name.isEmpty) name = MirrorSystem.getName(key);
2016-06-27 00:20:42 +00:00
routeMappings[name] = route;
2016-06-27 00:20:42 +00:00
}
}
2016-11-23 09:10:47 +00:00
};
}
2016-11-28 21:48:00 +00:00
void configureRoutes(Routable routable) {
ClassMirror classMirror = reflectClass(this.runtimeType);
2016-11-23 09:10:47 +00:00
InstanceMirror instanceMirror = reflect(this);
2016-11-28 21:48:00 +00:00
final handlers = []..addAll(exposeDecl.middleware)..addAll(middleware);
2016-11-23 09:10:47 +00:00
final callback = _callback(instanceMirror, routable, handlers);
classMirror.instanceMembers.forEach(callback);
}
2016-10-22 20:41:36 +00:00
}