diff --git a/CHANGELOG.md b/CHANGELOG.md index 8df5a275..58c1361d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,4 +42,7 @@ take routes in the form of `FutureOr myFunc(RequestContext, ResponseContext res) * `@Expose.middleware` now takes `Iterable`, instead of just `List`. * `createDynamicHandler` was renamed to `ioc`, and is now used to run IoC-aware handlers in a type-safe manner. -* `RequestContext.params` is now a `Map`, rather than just a `Map`. \ No newline at end of file +* `RequestContext.params` is now a `Map`, rather than just a `Map`. +* Removed `RequestContext.grab`. +* Removed `RequestContext.properties`. +* Removed the defunct `debug` property where it still existed. \ No newline at end of file diff --git a/lib/src/core/injection.dart b/lib/src/core/injection.dart index b6228a27..e87c485c 100644 --- a/lib/src/core/injection.dart +++ b/lib/src/core/injection.dart @@ -1,12 +1,11 @@ part of angel_framework.http.request_context; -const List _primitiveTypes = [String, int, num, double, Null]; +const List _primitiveTypes = [String, int, num, double, Null]; /// Shortcut for calling [preInject], and then [handleContained]. /// /// Use this to instantly create a request handler for a DI-enabled method. -RequestHandler ioc(Function handler, - {Iterable optional: const []}) { +RequestHandler ioc(Function handler, {Iterable optional: const []}) { var injection = preInject(handler); injection.optional.addAll(optional ?? []); return handleContained(handler, injection); @@ -29,11 +28,7 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req, } else if (requirement is String) { if (req.params.containsKey(requirement)) { return req.params[requirement]; - } else if (req._injections.containsKey(requirement)) - return req._injections[requirement]; - else if (req.properties.containsKey(requirement)) - return req.properties[requirement]; - else if ((propFromApp = req.app.findProperty(requirement)) != null) + } else if ((propFromApp = req.app.findProperty(requirement)) != null) return propFromApp; else if (injection.optional.contains(requirement)) return null; @@ -48,18 +43,13 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req, String key = requirement.first; Type type = requirement.last; if (req.params.containsKey(key) || - req._injections.containsKey(key) || - req.properties.containsKey(key) || req.app.configuration.containsKey(key) || _primitiveTypes.contains(type)) { return resolveInjection(key, injection, req, res, throwOnUnresolved); } else return resolveInjection(type, injection, req, res, throwOnUnresolved); } else if (requirement is Type && requirement != dynamic) { - if (req._injections.containsKey(requirement)) - return req._injections[requirement]; - else - return req.app.container.make(requirement); + return req.app.container.make(requirement); } else if (throwOnUnresolved) { throw new ArgumentError( '$requirement cannot be injected into a request handler.'); diff --git a/lib/src/core/request_context.dart b/lib/src/core/request_context.dart index a8c4530c..da47bef1 100644 --- a/lib/src/core/request_context.dart +++ b/lib/src/core/request_context.dart @@ -24,8 +24,6 @@ abstract class RequestContext { BodyParseResult _body; Map _provisionalQuery; - final Map properties = {}; - /// The underlying [RawRequest] provided by the driver. RawRequest get rawRequest; @@ -87,31 +85,6 @@ abstract class RequestContext { /// Includes the leading `.`, if there is one. String get extension => _extensionCache ??= p.extension(uri.path); - /// Grabs an object by key or type from [params], [_injections], or - /// [app].container. Use this to perform dependency injection - /// within a service hook. - T grab(key) { - if (params.containsKey(key)) - return params[key] as T; - else if (_injections.containsKey(key)) - return _injections[key] as T; - else if (properties.containsKey(key)) - return properties[key] as T; - else { - var prop = app?.findProperty(key); - if (prop != null) - return prop as T; - else if (key is Type) { - try { - return app.container.make(key) as T; - } catch (e) { - return null; - } - } else - return null; - } - } - /// Returns `true` if the client's `Accept` header indicates that the given [contentType] is considered a valid response. /// /// You cannot provide a `null` [contentType]. @@ -148,7 +121,8 @@ abstract class RequestContext { Future parseBody() => parse().then((b) => b.body); /// Retrieves a list of all uploaded files if it has already been parsed, or lazy-parses it before returning the files. - Future> parseUploadedFiles() => parse().then((b) => b.files); + Future> parseUploadedFiles() => + parse().then((b) => b.files); /// Retrieves the original request buffer if it has already been parsed, or lazy-parses it before returning the buffer.. /// @@ -185,8 +159,6 @@ abstract class RequestContext { _acceptsAllCache = null; _acceptHeaderCache = null; _provisionalQuery?.clear(); - properties.clear(); - _injections.clear(); serviceParams.clear(); params.clear(); return new Future.value(); diff --git a/lib/src/core/response_context.dart b/lib/src/core/response_context.dart index fa3d5482..e1877cde 100644 --- a/lib/src/core/response_context.dart +++ b/lib/src/core/response_context.dart @@ -9,7 +9,6 @@ import 'package:angel_route/angel_route.dart'; import 'package:file/file.dart'; import 'package:http_parser/http_parser.dart'; import 'package:mime/mime.dart'; -import 'package:pool/pool.dart'; import '../http/http.dart'; import 'request_context.dart'; @@ -18,7 +17,8 @@ import 'server.dart' show Angel; final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); /// A convenience wrapper around an outgoing HTTP request. -abstract class ResponseContext implements StreamSink>, StringSink { +abstract class ResponseContext + implements StreamSink>, StringSink { final Map properties = {}; final BytesBuilder _buffer = new _LockableBytesBuilder(); final Map _headers = {'server': 'angel'}; @@ -313,12 +313,9 @@ abstract class ResponseContext implements StreamSink>, St /// Releases critical resources from the [correspondingRequest]. void releaseCorrespondingRequest() { - if (correspondingRequest?.injections?.containsKey(Stopwatch) == true) { - (correspondingRequest.injections[Stopwatch] as Stopwatch).stop(); - } - - if (correspondingRequest?.injections?.containsKey(PoolResource) == true) { - (correspondingRequest.injections[PoolResource] as PoolResource).release(); + if (!correspondingRequest.app.isProduction && + correspondingRequest.app.logger != null) { + correspondingRequest.container.make().stop(); } } diff --git a/lib/src/core/server.dart b/lib/src/core/server.dart index 88d42e65..115a1c60 100644 --- a/lib/src/core/server.dart +++ b/lib/src/core/server.dart @@ -34,7 +34,8 @@ class Angel extends Routable { (String view, [Map data]) => 'No view engine has been configured yet.'; final List _children = []; - final Map>>> + final Map, ParseResult>>> handlerCache = new HashMap(); Router _flattened; diff --git a/lib/src/core/service.dart b/lib/src/core/service.dart index dfb3d8e9..cdba7ecc 100644 --- a/lib/src/core/service.dart +++ b/lib/src/core/service.dart @@ -8,7 +8,6 @@ import 'package:merge_map/merge_map.dart'; import '../util.dart'; import 'hooked_service.dart' show HookedService; import 'metadata.dart'; -import 'request_context.dart'; import 'response_context.dart'; import 'routable.dart'; import 'server.dart'; diff --git a/lib/src/http/angel_http.dart b/lib/src/http/angel_http.dart index c4a750fc..d3055c31 100644 --- a/lib/src/http/angel_http.dart +++ b/lib/src/http/angel_http.dart @@ -8,14 +8,16 @@ import 'dart:io' HttpServer, Platform, SecurityContext; + import 'package:angel_http_exception/angel_http_exception.dart'; import 'package:angel_route/angel_route.dart'; import 'package:combinator/combinator.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:tuple/tuple.dart'; + +import '../core/core.dart'; import 'http_request_context.dart'; import 'http_response_context.dart'; -import '../core/core.dart'; final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)'); @@ -60,7 +62,7 @@ class AngelHttp { /// the server. factory AngelHttp.secure( Angel app, String certificateChainPath, String serverKeyPath, - {bool debug: false, String password, bool useZone: true}) { + { String password, bool useZone: true}) { var certificateChain = Platform.script.resolve(certificateChainPath).toFilePath(); var serverKey = Platform.script.resolve(serverKeyPath).toFilePath(); @@ -107,14 +109,16 @@ class AngelHttp { var path = req.path; if (path == '/') path = ''; - Tuple3>> resolveTuple() { + Tuple3, ParseResult>> + resolveTuple() { Router r = app.optimizedRouter; var resolved = r.resolveAbsolute(path, method: req.method, strip: false); return new Tuple3( new MiddlewarePipeline(resolved).handlers, - resolved.fold({}, (out, r) => out..addAll(r.allParams)), + resolved.fold>( + {}, (out, r) => out..addAll(r.allParams)), resolved.isEmpty ? null : resolved.first.parseResult, ); } @@ -125,10 +129,15 @@ class AngelHttp { : resolveTuple(); req.params.addAll(tuple.item2); - req.inject(ParseResult, tuple.item3); - if (!app.isProduction && app.logger != null) - req.inject(Stopwatch, new Stopwatch()..start()); + req.container.registerSingleton>>( + tuple.item3); + req.container.registerSingleton(tuple.item3); + + if (!app.isProduction && app.logger != null) { + req.container + .registerSingleton(new Stopwatch()..start()); + } var pipeline = tuple.item1; @@ -215,8 +224,9 @@ class AngelHttp { ); var zone = Zone.current.fork(specification: zoneSpec); - req.inject(Zone, zone); - req.inject(ZoneSpecification, zoneSpec); + req.container.registerSingleton(zone); + req.container.registerSingleton(zoneSpec); + return zone.run(handle).whenComplete(() { res.dispose(); }); @@ -321,7 +331,7 @@ class AngelHttp { return request.response.close().then((_) { if (!app.isProduction && app.logger != null) { - var sw = req.grab(Stopwatch); + var sw = req.container.make(); if (sw.isRunning) { sw?.stop(); diff --git a/lib/src/http/controller.dart b/lib/src/http/controller.dart index d910cb9a..cd01d135 100644 --- a/lib/src/http/controller.dart +++ b/lib/src/http/controller.dart @@ -15,8 +15,6 @@ class Controller { /// The [Angel] application powering this controller. Angel get app => _app; - final bool debug; - /// If `true` (default), this class will inject itself as a singleton into the [app]'s container when bootstrapped. final bool injectSingleton; @@ -26,7 +24,7 @@ class Controller { /// A mapping of route paths to routes, produced from the [Expose] annotations on this class. Map routeMappings = {}; - Controller({this.debug: false, this.injectSingleton: true}); + Controller({this.injectSingleton: true}); @mustCallSuper Future configureServer(Angel app) { diff --git a/test/primitives_test.dart b/test/primitives_test.dart index 25a7ffde..66df81ab 100644 --- a/test/primitives_test.dart +++ b/test/primitives_test.dart @@ -12,7 +12,7 @@ main() { setUp(() { app = new Angel(reflector: MirrorsReflector()) - ..inject('global', 305); // Pitbull! + ..configuration['global'] = 305; // Pitbull! http = new AngelHttp(app); app.get('/string/:string', ioc((String string) => string)); diff --git a/test/server_test.dart b/test/server_test.dart index a3d81493..44d9015f 100644 --- a/test/server_test.dart +++ b/test/server_test.dart @@ -89,7 +89,8 @@ main() { }); test('global injection added to injection map', () async { - var app = new Angel(reflector: MirrorsReflector())..inject('a', 'b'); + var app = new Angel(reflector: MirrorsReflector()) + ..configuration['a'] = 'b'; var http = new AngelHttp(app); app.get('/', ioc((String a) => a)); var rq = new MockHttpRequest('GET', Uri.parse('/'))..close();