Fixed preprocessing?
This commit is contained in:
parent
b05fc64f1f
commit
ce28fa338b
2 changed files with 61 additions and 49 deletions
|
@ -3,12 +3,11 @@ library angel_framework.http.controller;
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:mirrors';
|
import 'dart:mirrors';
|
||||||
import 'package:angel_route/angel_route.dart';
|
import 'package:angel_route/angel_route.dart';
|
||||||
import 'angel_http_exception.dart';
|
|
||||||
import 'metadata.dart';
|
import 'metadata.dart';
|
||||||
import 'request_context.dart';
|
import 'request_context.dart';
|
||||||
import 'response_context.dart';
|
import 'response_context.dart';
|
||||||
import 'routable.dart';
|
import 'routable.dart';
|
||||||
import 'server.dart' show Angel;
|
import 'server.dart' show Angel, preInject;
|
||||||
|
|
||||||
/// Contains a list of the data required for a DI-enabled method to run.
|
/// Contains a list of the data required for a DI-enabled method to run.
|
||||||
///
|
///
|
||||||
|
@ -30,7 +29,6 @@ class Controller {
|
||||||
final bool debug;
|
final bool debug;
|
||||||
List middleware = [];
|
List middleware = [];
|
||||||
Map<String, Route> routeMappings = {};
|
Map<String, Route> routeMappings = {};
|
||||||
Expose exposeDecl;
|
|
||||||
|
|
||||||
Controller({this.debug: false});
|
Controller({this.debug: false});
|
||||||
|
|
||||||
|
@ -39,9 +37,7 @@ class Controller {
|
||||||
|
|
||||||
// Load global expose decl
|
// Load global expose decl
|
||||||
ClassMirror classMirror = reflectClass(this.runtimeType);
|
ClassMirror classMirror = reflectClass(this.runtimeType);
|
||||||
Expose exposeDecl = classMirror.metadata
|
Expose exposeDecl = findExpose();
|
||||||
.map((m) => m.reflectee)
|
|
||||||
.firstWhere((r) => r is Expose, orElse: () => null);
|
|
||||||
|
|
||||||
if (exposeDecl == null) {
|
if (exposeDecl == null) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
@ -83,7 +79,6 @@ class Controller {
|
||||||
|
|
||||||
var reflectedMethod = instanceMirror.getField(methodName).reflectee;
|
var reflectedMethod = instanceMirror.getField(methodName).reflectee;
|
||||||
var middleware = []..addAll(handlers)..addAll(exposeDecl.middleware);
|
var middleware = []..addAll(handlers)..addAll(exposeDecl.middleware);
|
||||||
var injection = new InjectionRequest();
|
|
||||||
|
|
||||||
// Check if normal
|
// Check if normal
|
||||||
if (method.parameters.length == 2 &&
|
if (method.parameters.length == 2 &&
|
||||||
|
@ -95,26 +90,8 @@ class Controller {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load parameters
|
|
||||||
for (var parameter in method.parameters) {
|
|
||||||
var name = MirrorSystem.getName(parameter.simpleName);
|
|
||||||
var type = parameter.type.reflectedType;
|
|
||||||
|
|
||||||
if (type == RequestContext || type == ResponseContext) {
|
|
||||||
injection.required.add(type);
|
|
||||||
} else if (name == 'req') {
|
|
||||||
injection.required.add(RequestContext);
|
|
||||||
} else if (name == 'res') {
|
|
||||||
injection.required.add(ResponseContext);
|
|
||||||
} else if (type == dynamic) {
|
|
||||||
injection.required.add(name);
|
|
||||||
} else {
|
|
||||||
injection.required.add([name, type]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
routable.addRoute(exposeDecl.method, exposeDecl.path,
|
routable.addRoute(exposeDecl.method, exposeDecl.path,
|
||||||
handleContained(reflectedMethod, injection),
|
handleContained(reflectedMethod, preInject(reflectedMethod)),
|
||||||
middleware: middleware);
|
middleware: middleware);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -122,6 +99,12 @@ class Controller {
|
||||||
|
|
||||||
/// Used to add additional routes to the router from within a [Controller].
|
/// Used to add additional routes to the router from within a [Controller].
|
||||||
void configureRoutes(Routable routable) {}
|
void configureRoutes(Routable routable) {}
|
||||||
|
|
||||||
|
/// Finds the [Expose] declaration for this class.
|
||||||
|
Expose findExpose() => reflectClass(runtimeType)
|
||||||
|
.metadata
|
||||||
|
.map((m) => m.reflectee)
|
||||||
|
.firstWhere((r) => r is Expose, orElse: () => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a request with a DI-enabled handler.
|
/// Handles a request with a DI-enabled handler.
|
||||||
|
@ -140,7 +123,7 @@ RequestHandler handleContained(handler, InjectionRequest injection) {
|
||||||
.containsKey(requirement))
|
.containsKey(requirement))
|
||||||
args.add(req.injections[requirement]);
|
args.add(req.injections[requirement]);
|
||||||
else {
|
else {
|
||||||
throw new Exception(
|
throw new ArgumentError(
|
||||||
"Cannot resolve parameter '$requirement' within handler.");
|
"Cannot resolve parameter '$requirement' within handler.");
|
||||||
}
|
}
|
||||||
args.add(req.params[requirement]);
|
args.add(req.params[requirement]);
|
||||||
|
|
|
@ -126,6 +126,7 @@ class Angel extends AngelBase {
|
||||||
Future<HttpServer> startServer([InternetAddress address, int port]) async {
|
Future<HttpServer> startServer([InternetAddress address, int port]) async {
|
||||||
final host = address ?? InternetAddress.LOOPBACK_IP_V4;
|
final host = address ?? InternetAddress.LOOPBACK_IP_V4;
|
||||||
this.httpServer = await _serverGenerator(host, port ?? 0);
|
this.httpServer = await _serverGenerator(host, port ?? 0);
|
||||||
|
preprocessRoutes();
|
||||||
return httpServer..listen(handleRequest);
|
return httpServer..listen(handleRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +285,27 @@ class Angel extends AngelBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Preprocesses all routes, and eliminates the burden of reflecting handlers
|
||||||
|
/// at run-time.
|
||||||
|
void preprocessRoutes() {
|
||||||
|
_add(v) {
|
||||||
|
if (v is Function && !_preContained.containsKey(v)) {
|
||||||
|
_preContained[v] = preInject(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _walk(Router router) {
|
||||||
|
router.requestMiddleware.forEach((k, v) => _add(v));
|
||||||
|
router.middleware.forEach(_add);
|
||||||
|
router.routes
|
||||||
|
.where((r) => r is SymlinkRoute)
|
||||||
|
.map((SymlinkRoute r) => r.router)
|
||||||
|
.forEach(_walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
_walk(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// Run a function after injecting from service container.
|
/// Run a function after injecting from service container.
|
||||||
/// If this function has been reflected before, then
|
/// If this function has been reflected before, then
|
||||||
/// the execution will be faster, as the injection requirements were stored beforehand.
|
/// the execution will be faster, as the injection requirements were stored beforehand.
|
||||||
|
@ -299,26 +321,7 @@ class Angel extends AngelBase {
|
||||||
/// Runs with DI, and *always* reflects. Prefer [runContained].
|
/// Runs with DI, and *always* reflects. Prefer [runContained].
|
||||||
Future runReflected(
|
Future runReflected(
|
||||||
Function handler, RequestContext req, ResponseContext res) async {
|
Function handler, RequestContext req, ResponseContext res) async {
|
||||||
ClosureMirror closureMirror = reflect(handler);
|
var injection = preInjection(handler);
|
||||||
var injection = new InjectionRequest();
|
|
||||||
|
|
||||||
// Load parameters
|
|
||||||
for (var parameter in closureMirror.function.parameters) {
|
|
||||||
var name = MirrorSystem.getName(parameter.simpleName);
|
|
||||||
var type = parameter.type.reflectedType;
|
|
||||||
|
|
||||||
if (type == RequestContext || type == ResponseContext) {
|
|
||||||
injection.required.add(type);
|
|
||||||
} else if (name == 'req') {
|
|
||||||
injection.required.add(RequestContext);
|
|
||||||
} else if (name == 'res') {
|
|
||||||
injection.required.add(ResponseContext);
|
|
||||||
} else if (type == dynamic) {
|
|
||||||
injection.required.add(name);
|
|
||||||
} else {
|
|
||||||
injection.required.add([name, type]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_preContained[handler] = injection;
|
_preContained[handler] = injection;
|
||||||
return handleContained(handler, injection);
|
return handleContained(handler, injection);
|
||||||
|
@ -330,13 +333,13 @@ class Angel extends AngelBase {
|
||||||
await configurer(this);
|
await configurer(this);
|
||||||
|
|
||||||
if (configurer is Controller)
|
if (configurer is Controller)
|
||||||
_onController.add(controllers[configurer.exposeDecl.path] = configurer);
|
_onController.add(controllers[configurer.findExpose().path] = configurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fallback when an error is thrown while handling a request.
|
/// Fallback when an error is thrown while handling a request.
|
||||||
void failSilently(HttpRequest request, ResponseContext res) {}
|
void failSilently(HttpRequest request, ResponseContext res) {}
|
||||||
|
|
||||||
/// Starts the server.
|
/// Starts the server, wrapped in a [runZoned] call.
|
||||||
void listen({InternetAddress address, int port: 3000}) {
|
void listen({InternetAddress address, int port: 3000}) {
|
||||||
runZoned(() async {
|
runZoned(() async {
|
||||||
await startServer(address, port);
|
await startServer(address, port);
|
||||||
|
@ -433,3 +436,29 @@ class Angel extends AngelBase {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Predetermines what needs to be injected for a handler to run.
|
||||||
|
InjectionRequest preInject(Function handler) {
|
||||||
|
ClosureMirror closureMirror = reflect(handler);
|
||||||
|
var injection = new InjectionRequest();
|
||||||
|
|
||||||
|
// Load parameters
|
||||||
|
for (var parameter in closureMirror.function.parameters) {
|
||||||
|
var name = MirrorSystem.getName(parameter.simpleName);
|
||||||
|
var type = parameter.type.reflectedType;
|
||||||
|
|
||||||
|
if (type == RequestContext || type == ResponseContext) {
|
||||||
|
injection.required.add(type);
|
||||||
|
} else if (name == 'req') {
|
||||||
|
injection.required.add(RequestContext);
|
||||||
|
} else if (name == 'res') {
|
||||||
|
injection.required.add(ResponseContext);
|
||||||
|
} else if (type == dynamic) {
|
||||||
|
injection.required.add(name);
|
||||||
|
} else {
|
||||||
|
injection.required.add([name, type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return injection;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue