This commit is contained in:
thosakwe 2017-01-20 17:40:48 -05:00
parent 929e7bbac6
commit 4c04e1193c
4 changed files with 99 additions and 76 deletions

View file

@ -1,6 +1,6 @@
# angel_framework # angel_framework
[![pub 1.0.0-dev.48](https://img.shields.io/badge/pub-1.0.0--dev.48-red.svg)](https://pub.dartlang.org/packages/angel_framework) [![pub 1.0.0-dev.49](https://img.shields.io/badge/pub-1.0.0--dev.49-red.svg)](https://pub.dartlang.org/packages/angel_framework)
[![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework) [![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework)
Core libraries for the Angel Framework. Core libraries for the Angel Framework.

View file

@ -41,6 +41,16 @@ class HookedService extends Service {
if (inner.app != null) this.app = inner.app; if (inner.app != null) this.app = inner.app;
} }
RequestContext _getRequest(Map params) {
if (params == null) return null;
return params['__requestctx'];
}
ResponseContext _getResponse(Map params) {
if (params == null) return null;
return params['__responsectx'];
}
Map _stripReq(Map params) { Map _stripReq(Map params) {
if (params == null) if (params == null)
return params; return params;
@ -192,21 +202,21 @@ class HookedService extends Service {
Future<List> index([Map _params]) async { Future<List> index([Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeIndexed._emit( HookedServiceEvent before = await beforeIndexed._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params)); params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await beforeIndexed._emit( HookedServiceEvent after = await beforeIndexed._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params, result: before.result)); params: params, result: before.result));
return after.result; return after.result;
} }
List result = await inner.index(params); List result = await inner.index(params);
HookedServiceEvent after = await afterIndexed._emit( HookedServiceEvent after = await afterIndexed._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.INDEXED, _getResponse(_params), inner, HookedServiceEvent.INDEXED,
params: params, result: result)); params: params, result: result));
return after.result; return after.result;
} }
@ -215,22 +225,22 @@ class HookedService extends Service {
Future read(id, [Map _params]) async { Future read(id, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeRead._emit( HookedServiceEvent before = await beforeRead._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params)); id: id, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterRead._emit( HookedServiceEvent after = await afterRead._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params, result: before.result)); id: id, params: params, result: before.result));
return after.result; return after.result;
} }
var result = await inner.read(id, params); var result = await inner.read(id, params);
HookedServiceEvent after = await afterRead._emit( HookedServiceEvent after = await afterRead._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.READ, _getResponse(_params), inner, HookedServiceEvent.READ,
id: id, params: params, result: result)); id: id, params: params, result: result));
return after.result; return after.result;
} }
@ -239,22 +249,22 @@ class HookedService extends Service {
Future create(data, [Map _params]) async { Future create(data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeCreated._emit( HookedServiceEvent before = await beforeCreated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params)); data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterCreated._emit( HookedServiceEvent after = await afterCreated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params, result: before.result)); data: data, params: params, result: before.result));
return after.result; return after.result;
} }
var result = await inner.create(data, params); var result = await inner.create(data, params);
HookedServiceEvent after = await afterCreated._emit( HookedServiceEvent after = await afterCreated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.CREATED, _getResponse(_params), inner, HookedServiceEvent.CREATED,
data: data, params: params, result: result)); data: data, params: params, result: result));
return after.result; return after.result;
} }
@ -263,22 +273,22 @@ class HookedService extends Service {
Future modify(id, data, [Map _params]) async { Future modify(id, data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeModified._emit( HookedServiceEvent before = await beforeModified._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params)); id: id, data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterModified._emit( HookedServiceEvent after = await afterModified._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params, result: before.result)); id: id, data: data, params: params, result: before.result));
return after.result; return after.result;
} }
var result = await inner.modify(id, data, params); var result = await inner.modify(id, data, params);
HookedServiceEvent after = await afterModified._emit( HookedServiceEvent after = await afterModified._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.MODIFIED, _getResponse(_params), inner, HookedServiceEvent.MODIFIED,
id: id, data: data, params: params, result: result)); id: id, data: data, params: params, result: result));
return after.result; return after.result;
} }
@ -287,22 +297,22 @@ class HookedService extends Service {
Future update(id, data, [Map _params]) async { Future update(id, data, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeUpdated._emit( HookedServiceEvent before = await beforeUpdated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params)); id: id, data: data, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterUpdated._emit( HookedServiceEvent after = await afterUpdated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params, result: before.result)); id: id, data: data, params: params, result: before.result));
return after.result; return after.result;
} }
var result = await inner.update(id, data, params); var result = await inner.update(id, data, params);
HookedServiceEvent after = await afterUpdated._emit( HookedServiceEvent after = await afterUpdated._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.UPDATED, _getResponse(_params), inner, HookedServiceEvent.UPDATED,
id: id, data: data, params: params, result: result)); id: id, data: data, params: params, result: result));
return after.result; return after.result;
} }
@ -311,29 +321,30 @@ class HookedService extends Service {
Future remove(id, [Map _params]) async { Future remove(id, [Map _params]) async {
var params = _stripReq(_params); var params = _stripReq(_params);
HookedServiceEvent before = await beforeRemoved._emit( HookedServiceEvent before = await beforeRemoved._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params)); id: id, params: params));
if (before._canceled) { if (before._canceled) {
HookedServiceEvent after = await afterRemoved._emit( HookedServiceEvent after = await afterRemoved._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params, result: before.result)); id: id, params: params, result: before.result));
return after.result; return after.result;
} }
var result = await inner.remove(id, params); var result = await inner.remove(id, params);
HookedServiceEvent after = await afterRemoved._emit( HookedServiceEvent after = await afterRemoved._emit(
new HookedServiceEvent._base(_params['__requestctx'], new HookedServiceEvent._base(_getRequest(_params),
params['__responsectx'], inner, HookedServiceEvent.REMOVED, _getResponse(_params), inner, HookedServiceEvent.REMOVED,
id: id, params: params, result: result)); id: id, params: params, result: result));
return after.result; return after.result;
} }
/// Fires an `after` event. This will not be propagated to clients, /// Fires an `after` event. This will not be propagated to clients,
/// but will be broadcasted to WebSockets, etc. /// but will be broadcasted to WebSockets, etc.
Future<HookedServiceEvent> fire(String eventName, result, [HookedServiceEventListener callback]) async { Future<HookedServiceEvent> fire(String eventName, result,
[HookedServiceEventListener callback]) async {
HookedServiceEventDispatcher dispatcher; HookedServiceEventDispatcher dispatcher;
switch (eventName) { switch (eventName) {

View file

@ -124,7 +124,7 @@ class Angel extends AngelBase {
/// ///
/// Returns false on failure; otherwise, returns the HttpServer. /// Returns false on failure; otherwise, returns the HttpServer.
Future<HttpServer> startServer([InternetAddress address, int port]) async { Future<HttpServer> startServer([InternetAddress address, int port]) async {
final host = address ?? InternetAddress.LOOPBACK_IP_V4; var host = address ?? InternetAddress.LOOPBACK_IP_V4;
this.httpServer = await _serverGenerator(host, port ?? 0); this.httpServer = await _serverGenerator(host, port ?? 0);
preprocessRoutes(); preprocessRoutes();
return httpServer..listen(handleRequest); return httpServer..listen(handleRequest);
@ -188,38 +188,44 @@ class Angel extends AngelBase {
return false; return false;
} }
Future<RequestContext> createRequestContext(HttpRequest request) {
_beforeProcessed.add(request);
return RequestContext.from(request, this);
}
Future<ResponseContext> createResponseContext(HttpResponse response) async =>
new ResponseContext(response, this);
/// Handles a single request. /// Handles a single request.
Future handleRequest(HttpRequest request) async { Future handleRequest(HttpRequest request) async {
try { try {
_beforeProcessed.add(request); var req = await createRequestContext(request);
var res = await createResponseContext(request.response);
final req = await RequestContext.from(request, this);
final res = new ResponseContext(request.response, this);
String requestedUrl = request.uri.path.replaceAll(_straySlashes, ''); String requestedUrl = request.uri.path.replaceAll(_straySlashes, '');
if (requestedUrl.isEmpty) requestedUrl = '/'; if (requestedUrl.isEmpty) requestedUrl = '/';
final resolved = var resolved =
resolveAll(requestedUrl, requestedUrl, method: request.method); resolveAll(requestedUrl, requestedUrl, method: request.method);
for (final result in resolved) req.params.addAll(result.allParams); for (var result in resolved) req.params.addAll(result.allParams);
if (resolved.isNotEmpty) { if (resolved.isNotEmpty) {
final route = resolved.first.route; var route = resolved.first.route;
req.inject(Match, route.match(requestedUrl)); req.inject(Match, route.match(requestedUrl));
} }
final m = new MiddlewarePipeline(resolved); var m = new MiddlewarePipeline(resolved);
req.inject(MiddlewarePipeline, m); req.inject(MiddlewarePipeline, m);
final pipeline = []..addAll(before)..addAll(m.handlers)..addAll(after); var pipeline = []..addAll(before)..addAll(m.handlers)..addAll(after);
_printDebug('Handler sequence on $requestedUrl: $pipeline'); _printDebug('Handler sequence on $requestedUrl: $pipeline');
for (final handler in pipeline) { for (var handler in pipeline) {
try { try {
_printDebug('Executing handler: $handler'); _printDebug('Executing handler: $handler');
final result = await executeHandler(handler, req, res); var result = await executeHandler(handler, req, res);
_printDebug('Result: $result'); _printDebug('Result: $result');
if (!result) { if (!result) {
@ -262,27 +268,7 @@ class Angel extends AngelBase {
} }
try { try {
_afterProcessed.add(request); await sendRequest(request, req, res);
if (!res.willCloseItself) {
for (var finalizer in responseFinalizers) {
await finalizer(req, res);
}
for (var key in res.headers.keys) {
request.response.headers.add(key, res.headers[key]);
}
request.response.headers
..chunkedTransferEncoding = res.chunked ?? true
..set(HttpHeaders.CONTENT_LENGTH, res.buffer.length);
request.response
..statusCode = res.statusCode
..cookies.addAll(res.cookies)
..add(res.buffer.takeBytes());
await request.response.close();
}
} catch (e, st) { } catch (e, st) {
_fatalErrorStream _fatalErrorStream
.add(new AngelFatalError(request: request, error: e, stack: st)); .add(new AngelFatalError(request: request, error: e, stack: st));
@ -339,6 +325,32 @@ class Angel extends AngelBase {
// return await closureMirror.apply(args).reflectee; // return await closureMirror.apply(args).reflectee;
} }
/// Sends a response.
Future sendRequest(
HttpRequest request, RequestContext req, ResponseContext res) async {
_afterProcessed.add(request);
if (!res.willCloseItself) {
for (var finalizer in responseFinalizers) {
await finalizer(req, res);
}
for (var key in res.headers.keys) {
request.response.headers.add(key, res.headers[key]);
}
request.response.headers
..chunkedTransferEncoding = res.chunked ?? true
..set(HttpHeaders.CONTENT_LENGTH, res.buffer.length);
request.response
..statusCode = res.statusCode
..cookies.addAll(res.cookies)
..add(res.buffer.takeBytes());
await request.response.close();
}
}
/// Applies an [AngelConfigurer] to this instance. /// Applies an [AngelConfigurer] to this instance.
Future configure(AngelConfigurer configurer) async { Future configure(AngelConfigurer configurer) async {
await configurer(this); await configurer(this);
@ -366,7 +378,7 @@ class Angel extends AngelBase {
@override @override
use(Pattern path, Routable routable, use(Pattern path, Routable routable,
{bool hooked: true, String namespace: null}) { {bool hooked: true, String namespace: null}) {
final head = path.toString().replaceAll(_straySlashes, ''); var head = path.toString().replaceAll(_straySlashes, '');
if (routable is Angel) { if (routable is Angel) {
_children.add(routable.._parent = this); _children.add(routable.._parent = this);
@ -396,12 +408,12 @@ class Angel extends AngelBase {
} }
routable.controllers.forEach((k, v) { routable.controllers.forEach((k, v) {
final tail = k.toString().replaceAll(_straySlashes, ''); var tail = k.toString().replaceAll(_straySlashes, '');
controllers['$head/$tail'.replaceAll(_straySlashes, '')] = v; controllers['$head/$tail'.replaceAll(_straySlashes, '')] = v;
}); });
routable.services.forEach((k, v) { routable.services.forEach((k, v) {
final tail = k.toString().replaceAll(_straySlashes, ''); var tail = k.toString().replaceAll(_straySlashes, '');
services['$head/$tail'.replaceAll(_straySlashes, '')] = v; services['$head/$tail'.replaceAll(_straySlashes, '')] = v;
}); });
} }
@ -434,7 +446,7 @@ class Angel extends AngelBase {
/// the server. /// the server.
factory Angel.secure(String certificateChainPath, String serverKeyPath, factory Angel.secure(String certificateChainPath, String serverKeyPath,
{bool debug: false, String password}) { {bool debug: false, String password}) {
final app = new Angel(debug: debug == true); var app = new Angel(debug: debug == true);
app._serverGenerator = (InternetAddress address, int port) async { app._serverGenerator = (InternetAddress address, int port) async {
var certificateChain = var certificateChain =

View file

@ -1,5 +1,5 @@
name: angel_framework name: angel_framework
version: 1.0.0-dev.48 version: 1.0.0-dev.49
description: Core libraries for the Angel framework. description: Core libraries for the Angel framework.
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_framework homepage: https://github.com/angel-dart/angel_framework