54
This commit is contained in:
parent
0696705809
commit
6eebc7afa8
8 changed files with 127 additions and 32 deletions
|
@ -1,6 +1,6 @@
|
|||
# angel_framework
|
||||
|
||||
[![pub 1.0.0-dev.53](https://img.shields.io/badge/pub-1.0.0--dev.53-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||
[![pub 1.0.0-dev.54](https://img.shields.io/badge/pub-1.0.0--dev.54-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)
|
||||
|
||||
Core libraries for the Angel Framework.
|
||||
|
|
50
lib/src/http/anonymous_service.dart
Normal file
50
lib/src/http/anonymous_service.dart
Normal file
|
@ -0,0 +1,50 @@
|
|||
import 'dart:async';
|
||||
import 'service.dart';
|
||||
|
||||
/// An easy helper class to create one-off services without having to create an entire class.
|
||||
///
|
||||
/// Well-suited for testing.
|
||||
class AnonymousService extends Service {
|
||||
Function _index, _read, _create, _modify, _update, _remove;
|
||||
|
||||
AnonymousService(
|
||||
{Future<List> index([Map params]),
|
||||
Future read(id, [Map params]),
|
||||
Future create(data, [Map params]),
|
||||
Future modify(id, data, [Map params]),
|
||||
Future update(id, data, [Map params]),
|
||||
Future remove(id, [Map params])})
|
||||
: super() {
|
||||
_index = index;
|
||||
_read = read;
|
||||
_create = create;
|
||||
_modify = modify;
|
||||
_update = update;
|
||||
_remove = remove;
|
||||
}
|
||||
|
||||
@override
|
||||
index([Map params]) => _index != null ? _index(params) : super.index(params);
|
||||
|
||||
@override
|
||||
read(id, [Map params]) =>
|
||||
_read != null ? _read(id, params) : super.read(id, params);
|
||||
|
||||
@override
|
||||
create(data, [Map params]) =>
|
||||
_create != null ? _create(data, params) : super.create(data, params);
|
||||
|
||||
@override
|
||||
modify(id, data, [Map params]) => _modify != null
|
||||
? _modify(id, data, params)
|
||||
: super.modify(id, data, params);
|
||||
|
||||
@override
|
||||
update(id, data, [Map params]) => _update != null
|
||||
? _update(id, data, params)
|
||||
: super.update(id, data, params);
|
||||
|
||||
@override
|
||||
remove(id, [Map params]) =>
|
||||
_remove != null ? _remove(id, params) : super.remove(id, params);
|
||||
}
|
|
@ -138,7 +138,7 @@ class HookedService extends Service {
|
|||
get(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.read(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
.read(toId(req.params['id']), mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll((readMiddleware == null) ? [] : readMiddleware.handlers));
|
||||
|
@ -146,8 +146,8 @@ class HookedService extends Service {
|
|||
Middleware modifyMiddleware = getAnnotation(inner.modify, Middleware);
|
||||
patch(
|
||||
'/:id',
|
||||
(req, res) async => await this.modify(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.modify(toId(req.params['id']), req.body,
|
||||
mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -156,8 +156,8 @@ class HookedService extends Service {
|
|||
Middleware updateMiddleware = getAnnotation(inner.update, Middleware);
|
||||
post(
|
||||
'/:id',
|
||||
(req, res) async => await this.update(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.update(toId(req.params['id']), req.body,
|
||||
mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -166,8 +166,8 @@ class HookedService extends Service {
|
|||
Middleware removeMiddleware = getAnnotation(inner.remove, Middleware);
|
||||
delete(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.remove(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.remove(
|
||||
toId(req.params['id']), mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
|
|
@ -4,6 +4,7 @@ library angel_framework.http;
|
|||
export 'package:angel_route/angel_route.dart';
|
||||
export 'angel_base.dart';
|
||||
export 'angel_http_exception.dart';
|
||||
export 'anonymous_service.dart';
|
||||
export 'base_middleware.dart';
|
||||
export 'base_plugin.dart';
|
||||
export 'controller.dart';
|
||||
|
|
|
@ -8,11 +8,25 @@ import '../defs.dart';
|
|||
import 'angel_http_exception.dart';
|
||||
import 'service.dart';
|
||||
|
||||
int _getId(id) {
|
||||
try {
|
||||
return int.parse(id.toString());
|
||||
} catch (e) {
|
||||
throw new AngelHttpException.badRequest(message: 'Invalid ID.');
|
||||
}
|
||||
}
|
||||
|
||||
/// An in-memory [Service].
|
||||
class MemoryService<T> extends Service {
|
||||
Map <int, MemoryModel> items = {};
|
||||
/// If set to `true`, clients can remove all items by passing a `null` `id` to `remove`.
|
||||
///
|
||||
/// `false` by default.
|
||||
final bool allowRemoveAll;
|
||||
|
||||
MemoryService() :super() {
|
||||
//// The data contained in this service.
|
||||
final Map<int, MemoryModel> items = {};
|
||||
|
||||
MemoryService({this.allowRemoveAll: false}) : super() {
|
||||
if (!reflectType(T).isAssignableTo(reflectType(MemoryModel))) {
|
||||
throw new Exception(
|
||||
"MemoryServices only support classes that inherit from MemoryModel.");
|
||||
|
@ -31,19 +45,22 @@ class MemoryService<T> extends Service {
|
|||
}
|
||||
|
||||
Future read(id, [Map params]) async {
|
||||
int desiredId = int.parse(id.toString());
|
||||
int desiredId = _getId(id);
|
||||
if (items.containsKey(desiredId)) {
|
||||
MemoryModel found = items[desiredId];
|
||||
if (found != null) {
|
||||
return _makeJson(desiredId, found);
|
||||
} else throw new AngelHttpException.notFound();
|
||||
} else throw new AngelHttpException.notFound();
|
||||
} else
|
||||
throw new AngelHttpException.notFound();
|
||||
} else
|
||||
throw new AngelHttpException.notFound();
|
||||
}
|
||||
|
||||
Future create(data, [Map params]) async {
|
||||
//try {
|
||||
MemoryModel created = (data is MemoryModel) ? data : god.deserializeDatum(
|
||||
data, outputType: T);
|
||||
MemoryModel created = (data is MemoryModel)
|
||||
? data
|
||||
: god.deserializeDatum(data, outputType: T);
|
||||
|
||||
created.id = items.length;
|
||||
items[created.id] = created;
|
||||
|
@ -54,39 +71,50 @@ class MemoryService<T> extends Service {
|
|||
}
|
||||
|
||||
Future modify(id, data, [Map params]) async {
|
||||
int desiredId = int.parse(id.toString());
|
||||
int desiredId = _getId(id);
|
||||
if (items.containsKey(desiredId)) {
|
||||
try {
|
||||
Map existing = god.serializeObject(items[desiredId]);
|
||||
data = mergeMap([existing, data]);
|
||||
items[desiredId] =
|
||||
(data is Map) ? god.deserializeDatum(data, outputType: T) : data;
|
||||
(data is Map) ? god.deserializeDatum(data, outputType: T) : data;
|
||||
return _makeJson(desiredId, items[desiredId]);
|
||||
} catch (e) {
|
||||
throw new AngelHttpException.badRequest(message: 'Invalid data.');
|
||||
}
|
||||
} else throw new AngelHttpException.notFound();
|
||||
} else
|
||||
throw new AngelHttpException.notFound();
|
||||
}
|
||||
|
||||
Future update(id, data, [Map params]) async {
|
||||
int desiredId = int.parse(id.toString());
|
||||
int desiredId = _getId(id);
|
||||
if (items.containsKey(desiredId)) {
|
||||
try {
|
||||
items[desiredId] =
|
||||
(data is Map) ? god.deserializeDatum(data, outputType: T) : data;
|
||||
(data is Map) ? god.deserializeDatum(data, outputType: T) : data;
|
||||
return _makeJson(desiredId, items[desiredId]);
|
||||
} catch (e) {
|
||||
throw new AngelHttpException.badRequest(message: 'Invalid data.');
|
||||
}
|
||||
} else throw new AngelHttpException.notFound();
|
||||
} else
|
||||
throw new AngelHttpException.notFound();
|
||||
}
|
||||
|
||||
Future remove(id, [Map params]) async {
|
||||
int desiredId = int.parse(id.toString());
|
||||
if (id == null ||
|
||||
id == 'null' &&
|
||||
(allowRemoveAll == true ||
|
||||
params?.containsKey('provider') != true)) {
|
||||
items.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
int desiredId = _getId(id);
|
||||
if (items.containsKey(desiredId)) {
|
||||
MemoryModel item = items[desiredId];
|
||||
items[desiredId] = null;
|
||||
return _makeJson(desiredId, item);
|
||||
} else throw new AngelHttpException.notFound();
|
||||
} else
|
||||
throw new AngelHttpException.notFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,11 @@ class Angel extends AngelBase {
|
|||
/// Returns the parent instance of this application, if any.
|
||||
Angel get parent => _parent;
|
||||
|
||||
/// Plug-ins to be called right before server startup.
|
||||
///
|
||||
/// If the server is never started, they will never be called.
|
||||
final List<AngelConfigurer> justBeforeStart = [];
|
||||
|
||||
/// Always run before responses are sent.
|
||||
///
|
||||
/// These will only not run if an [AngelFatalError] occurs.
|
||||
|
@ -126,6 +131,7 @@ class Angel extends AngelBase {
|
|||
Future<HttpServer> startServer([InternetAddress address, int port]) async {
|
||||
var host = address ?? InternetAddress.LOOPBACK_IP_V4;
|
||||
this.httpServer = await _serverGenerator(host, port ?? 0);
|
||||
await Future.wait(justBeforeStart.map(configure));
|
||||
preprocessRoutes();
|
||||
return httpServer..listen(handleRequest);
|
||||
}
|
||||
|
@ -139,6 +145,7 @@ class Angel extends AngelBase {
|
|||
container.singleton(this);
|
||||
}
|
||||
|
||||
/// Runs some [handler]. Returns `true` if request execution should continue.
|
||||
Future<bool> executeHandler(
|
||||
handler, RequestContext req, ResponseContext res) async {
|
||||
if (handler is RequestMiddleware) {
|
||||
|
|
|
@ -68,6 +68,15 @@ class Service extends Routable {
|
|||
throw new AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Transforms an [id] string into one acceptable by a service.
|
||||
toId(String id) {
|
||||
if (id == 'null' || id == null)
|
||||
return null;
|
||||
else
|
||||
return id;
|
||||
}
|
||||
|
||||
/// Generates RESTful routes pointing to this class's methods.
|
||||
void addRoutes() {
|
||||
Map restProvider = {'provider': Providers.REST};
|
||||
|
||||
|
@ -100,7 +109,7 @@ class Service extends Routable {
|
|||
get(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.read(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
.read(toId(req.params['id']), mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll((readMiddleware == null) ? [] : readMiddleware.handlers));
|
||||
|
@ -108,8 +117,8 @@ class Service extends Routable {
|
|||
Middleware modifyMiddleware = getAnnotation(this.modify, Middleware);
|
||||
patch(
|
||||
'/:id',
|
||||
(req, res) async => await this.modify(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.modify(toId(req.params['id']), req.body,
|
||||
mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -118,8 +127,8 @@ class Service extends Routable {
|
|||
Middleware updateMiddleware = getAnnotation(this.update, Middleware);
|
||||
post(
|
||||
'/:id',
|
||||
(req, res) async => await this.update(
|
||||
req.params['id'], req.body, mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.update(toId(req.params['id']), req.body,
|
||||
mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
@ -128,8 +137,8 @@ class Service extends Routable {
|
|||
Middleware removeMiddleware = getAnnotation(this.remove, Middleware);
|
||||
delete(
|
||||
'/:id',
|
||||
(req, res) async => await this
|
||||
.remove(req.params['id'], mergeMap([req.query, restProvider])),
|
||||
(req, res) async => await this.remove(
|
||||
toId(req.params['id']), mergeMap([req.query, restProvider])),
|
||||
middleware: []
|
||||
..addAll(handlers)
|
||||
..addAll(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_framework
|
||||
version: 1.0.0-dev.53
|
||||
version: 1.0.0-dev.54
|
||||
description: Core libraries for the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
|
|
Loading…
Reference in a new issue