This commit is contained in:
regiostech 2016-06-19 01:02:41 -04:00
parent 315e0bca7a
commit 6cc9967b3e
7 changed files with 111 additions and 46 deletions

View file

@ -31,12 +31,12 @@ class AngelHttpException extends _AngelHttpExceptionBase {
/// Throws a 500 Internal Server Error.
/// Set includeRealException to true to print include the actual exception along with
/// this error. Useful flag for development vs. production.
AngelHttpException(Exception exception,
{bool includeRealException: false, StackTrace stackTrace}) :super.base() {
AngelHttpException(error,
{bool includeRealError: false, StackTrace stackTrace}) :super.base() {
statusCode = 500;
message = "500 Internal Server Error";
if (includeRealException) {
errors.add(exception.toString());
if (includeRealError) {
errors.add(error.toString());
if (stackTrace != null) {
errors.add(stackTrace.toString());
}

View file

@ -63,6 +63,7 @@ class Angel extends Routable {
if (e is AngelHttpException) {
// Special handling for AngelHttpExceptions :)
try {
res.status(e.statusCode);
String accept = request.headers.value(HttpHeaders.ACCEPT);
if (accept == "*/*" ||
accept.contains("application/json") ||

View file

@ -1,5 +1,15 @@
part of angel_framework.http;
class Providers {
final String via;
const Providers._base(String this.via);
static final Providers SERVER = const Providers._base('server_side');
static final Providers REST = const Providers._base('rest');
static final Providers WEBSOCKET = const Providers._base('websocket');
}
/// A data store exposed to the Internet.
class Service extends Routable {
/// The [Angel] app powering this service.
@ -16,17 +26,17 @@ class Service extends Routable {
}
/// Creates a resource.
Future create(Map data, [Map params]) {
Future create(data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed();
}
/// Modifies a resource.
Future modify(id, Map data, [Map params]) {
Future modify(id, data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed();
}
/// Overwrites a resource.
Future update(id, Map data, [Map params]) {
Future update(id, data, [Map params]) {
throw new AngelHttpException.MethodNotAllowed();
}
@ -36,19 +46,24 @@ class Service extends Routable {
}
Service() : super() {
get('/', (req, res) async => await this.index(req.query));
Map restProvider = {'provider': Providers.REST};
post('/', (req, res) async => await this.create(req.body));
get('/', (req, res) async => await this.index(
mergeMap([req.query, restProvider])));
post('/', (req, res) async => await this.create(
mergeMap([req.body, restProvider])));
get('/:id', (req, res) async =>
await this.read(req.params['id'], req.query));
await this.read(req.params['id'], mergeMap([req.query, restProvider])));
patch('/:id', (req, res) async => await this.modify(
req.params['id'], req.body));
req.params['id'], mergeMap([req.body, restProvider])));
post('/:id', (req, res) async => await this.update(
req.params['id'], req.body));
req.params['id'], mergeMap([req.body, restProvider])));
delete('/:id', (req, res) async => await this.remove(req.params['id'], req.query));
delete('/:id', (req, res) async => await this.remove(
req.params['id'], mergeMap([req.query, restProvider])));
}
}

View file

@ -1,25 +1,44 @@
part of angel_framework.http;
/// Wraps another service in a service that fires events on actions.
/// Wraps another service in a service that broadcasts events on actions.
class HookedService extends Service {
StreamController<List> _onIndexed = new StreamController<List>();
StreamController _onRead = new StreamController();
StreamController _onCreated = new StreamController();
StreamController _onModified = new StreamController();
StreamController _onUpdated = new StreamController();
StreamController _onRemoved = new StreamController();
StreamController<HookedServiceEvent> _beforeIndexed = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _beforeRead = new StreamController.broadcast();
StreamController<HookedServiceEvent> _beforeCreated = new StreamController.broadcast();
StreamController<HookedServiceEvent> _beforeModified = new StreamController.broadcast();
StreamController<HookedServiceEvent> _beforeUpdated = new StreamController.broadcast();
StreamController<HookedServiceEvent> _beforeRemoved = new StreamController.broadcast();
Stream<List> get onIndexed => _onIndexed.stream;
Stream<HookedServiceEvent> get beforeIndexed => _beforeIndexed.stream;
Stream get onRead => _onRead.stream;
Stream<HookedServiceEvent> get beforeRead => _beforeRead.stream;
Stream get onCreated => _onCreated.stream;
Stream<HookedServiceEvent> get beforeCreated => _beforeCreated.stream;
Stream get onModified => _onModified.stream;
Stream<HookedServiceEvent> get beforeModified => _beforeModified.stream;
Stream get onUpdated => _onUpdated.stream;
Stream<HookedServiceEvent> get beforeUpdated => _beforeUpdated.stream;
Stream get onRemoved => _onRemoved.stream;
Stream<HookedServiceEvent> get beforeRemoved => _beforeRemoved.stream;
StreamController<HookedServiceEvent> _afterIndexed = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _afterRead = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _afterCreated = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _afterModified = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _afterUpdated = new StreamController<HookedServiceEvent>.broadcast();
StreamController<HookedServiceEvent> _afterRemoved = new StreamController<HookedServiceEvent>.broadcast();
Stream<HookedServiceEvent> get afterIndexed => _afterIndexed.stream;
Stream<HookedServiceEvent> get afterRead => _afterRead.stream;
Stream<HookedServiceEvent> get afterCreated => _afterCreated.stream;
Stream<HookedServiceEvent> get afterModified => _afterModified.stream;
Stream<HookedServiceEvent> get afterUpdated => _afterUpdated.stream;
Stream<HookedServiceEvent> get afterRemoved => _afterRemoved.stream;
final Service inner;
@ -28,16 +47,26 @@ class HookedService extends Service {
@override
Future<List> index([Map params]) async {
List indexed = await inner.index(params);
_onIndexed.add(indexed);
return indexed;
HookedServiceEvent before = new HookedServiceEvent._base(inner, params: params);
_beforeIndexed.add(before);
if (before._canceled) {
HookedServiceEvent after = new HookedServiceEvent._base(inner, params: params, result: before.result);
_afterIndexed.add(after);
return before.result;
}
List result = await inner.index(params);
HookedServiceEvent after = new HookedServiceEvent._base(inner, params: params, result: result);
_afterIndexed.add(after);
return result;
}
@override
Future read(id, [Map params]) async {
var retrieved = await inner.read(id, params);
_onRead.add(retrieved);
_afterRead.add(retrieved);
return retrieved;
}
@ -45,14 +74,14 @@ class HookedService extends Service {
@override
Future create(data, [Map params]) async {
var created = await inner.create(data, params);
_onCreated.add(created);
_afterCreated.add(created);
return created;
}
@override
Future modify(id, data, [Map params]) async {
var modified = await inner.modify(id, data, params);
_onUpdated.add(modified);
_afterUpdated.add(modified);
return modified;
}
@ -60,14 +89,36 @@ class HookedService extends Service {
@override
Future update(id, data, [Map params]) async {
var updated = await inner.update(id, data, params);
_onUpdated.add(updated);
_afterUpdated.add(updated);
return updated;
}
@override
Future remove(id, [Map params]) async {
var removed = await inner.remove(id, params);
_onRemoved.add(removed);
_afterRemoved.add(removed);
return removed;
}
}
/// Fired when a hooked service is invoked.
class HookedServiceEvent {
/// Use this to end processing of an event.
void cancel(result) {
_canceled = true;
_result = result;
}
bool _canceled = false;
var id;
var data;
Map params;
var _result;
get result => _result;
/// The inner service whose method was hooked.
Service service;
HookedServiceEvent._base(Service this.service, {this.id, this.data, Map this.params: const{}, result}) {
_result = result;
}
}

View file

@ -5,7 +5,7 @@ class MemoryService<T> extends Service {
God god = new God();
Map <int, T> items = {};
makeJson(int index, T t) {
_makeJson(int index, T t) {
if (T == null || T == Map)
return mergeMap([god.serializeToMap(t), {'id': index}]);
else
@ -15,7 +15,7 @@ class MemoryService<T> extends Service {
Future<List> index([Map params]) async {
return items.keys
.where((index) => items[index] != null)
.map((index) => makeJson(index, items[index]))
.map((index) => _makeJson(index, items[index]))
.toList();
}
@ -24,7 +24,7 @@ class MemoryService<T> extends Service {
if (items.containsKey(desiredId)) {
T found = items[desiredId];
if (found != null) {
return makeJson(desiredId, found);
return _makeJson(desiredId, found);
} else throw new AngelHttpException.NotFound();
} else throw new AngelHttpException.NotFound();
}
@ -34,7 +34,7 @@ class MemoryService<T> extends Service {
items[items.length] =
(data is Map) ? god.deserializeFromMap(data, T) : data;
T created = items[items.length - 1];
return makeJson(items.length - 1, created);
return _makeJson(items.length - 1, created);
} catch (e) {
throw new AngelHttpException.BadRequest(message: 'Invalid data.');
}
@ -48,7 +48,7 @@ class MemoryService<T> extends Service {
data = mergeMap([existing, data]);
items[desiredId] =
(data is Map) ? god.deserializeFromMap(data, T) : data;
return makeJson(desiredId, items[desiredId]);
return _makeJson(desiredId, items[desiredId]);
} catch (e) {
throw new AngelHttpException.BadRequest(message: 'Invalid data.');
}
@ -61,7 +61,7 @@ class MemoryService<T> extends Service {
try {
items[desiredId] =
(data is Map) ? god.deserializeFromMap(data, T) : data;
return makeJson(desiredId, items[desiredId]);
return _makeJson(desiredId, items[desiredId]);
} catch (e) {
throw new AngelHttpException.BadRequest(message: 'Invalid data.');
}
@ -73,7 +73,7 @@ class MemoryService<T> extends Service {
if (items.containsKey(desiredId)) {
T item = items[desiredId];
items[desiredId] = null;
return makeJson(desiredId, item);
return _makeJson(desiredId, item);
} else throw new AngelHttpException.NotFound();
}

View file

@ -1,5 +1,5 @@
name: angel_framework
version: 0.0.0-dev.17
version: 0.0.0-dev.18
description: Core libraries for the Angel framework.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_framework
@ -7,7 +7,7 @@ dependencies:
body_parser: ">=1.0.0-dev <2.0.0"
json_god: ">=1.0.0 <2.0.0"
merge_map: ">=1.0.0 <2.0.0"
mime: ">=0.9.3 <0.10.0"
mime: ^0.9.3
dev_dependencies:
http: ">= 0.11.3 < 0.12.0"
test: ">= 0.12.13 < 0.13.0"

View file

@ -20,7 +20,6 @@ main() {
});
test('can use app.properties like members', () {
/*
angel.properties['hello'] = 'world';
angel.properties['foo'] = () => 'bar';
angel.properties['Foo'] = new Foo('bar');
@ -28,7 +27,6 @@ main() {
expect(angel.hello, equals('world'));
expect(angel.foo(), equals('bar'));
expect(angel.Foo.name, equals('bar'));
*/
});
});
}
}