Replace as Data cast in Service.dart with a method that throws a 400 on error

This commit is contained in:
Tobe O 2019-04-10 22:26:43 -04:00
parent 3802668cfc
commit 53b47dd43f
2 changed files with 34 additions and 12 deletions

View file

@ -6,6 +6,7 @@
* Allow setting of `bodyAsObject`, `bodyAsMap`, or `bodyAsList` **exactly once**. * Allow setting of `bodyAsObject`, `bodyAsMap`, or `bodyAsList` **exactly once**.
* Resolve named singletons in `resolveInjection`. * Resolve named singletons in `resolveInjection`.
* Fix a bug where `Service.parseId<double>` would attempt to parse an `int`. * Fix a bug where `Service.parseId<double>` would attempt to parse an `int`.
* Replace as Data cast in Service.dart with a method that throws a 400 on error.
# 2.0.0-alpha.24 # 2.0.0-alpha.24
* Add `AngelEnv` class to `core`. * Add `AngelEnv` class to `core`.

View file

@ -8,6 +8,7 @@ import '../util.dart';
import 'anonymous_service.dart'; import 'anonymous_service.dart';
import 'hooked_service.dart' show HookedService; import 'hooked_service.dart' show HookedService;
import 'metadata.dart'; import 'metadata.dart';
import 'request_context.dart';
import 'response_context.dart'; import 'response_context.dart';
import 'routable.dart'; import 'routable.dart';
import 'server.dart'; import 'server.dart';
@ -72,6 +73,26 @@ class Service<Id, Data> extends Routable {
/// Closes this service, including any database connections or stream controllers. /// Closes this service, including any database connections or stream controllers.
void close() {} void close() {}
/// An optional [readData] function can be passed to handle non-map/non-json bodies.
Service({FutureOr<Data> Function(RequestContext, ResponseContext) readData}) {
_readData = readData ??
(req, res) {
if (req.bodyAsObject is! Data) {
throw AngelHttpException.badRequest(
message:
'Invalid request body. Expected $Data; found ${req.bodyAsObject} instead.');
} else {
return req.bodyAsObject as Data;
}
};
}
FutureOr<Data> Function(RequestContext, ResponseContext) _readData;
/// A [Function] that reads the request body and converts it into [Data].
FutureOr<Data> Function(RequestContext, ResponseContext) get readData =>
_readData;
/// Retrieves the first object from the result of calling [index] with the given [params]. /// Retrieves the first object from the result of calling [index] with the given [params].
/// ///
/// If the result of [index] is `null`, OR an empty [Iterable], a 404 `AngelHttpException` will be thrown. /// If the result of [index] is `null`, OR an empty [Iterable], a 404 `AngelHttpException` will be thrown.
@ -215,10 +236,10 @@ class Service<Id, Data> extends Routable {
Middleware createMiddleware = Middleware createMiddleware =
getAnnotation<Middleware>(service.create, app.container.reflector); getAnnotation<Middleware>(service.create, app.container.reflector);
post('/', (req, ResponseContext res) { post('/', (req, ResponseContext res) {
return req.parseBody().then((_) { return req.parseBody().then((_) async {
return this return await this
.create( .create(
req.bodyAsMap as Data, await readData(req, res),
mergeMap([ mergeMap([
{'query': req.queryParameters}, {'query': req.queryParameters},
restProvider, restProvider,
@ -254,10 +275,10 @@ class Service<Id, Data> extends Routable {
Middleware modifyMiddleware = Middleware modifyMiddleware =
getAnnotation<Middleware>(service.modify, app.container.reflector); getAnnotation<Middleware>(service.modify, app.container.reflector);
patch('/:id', (req, res) { patch('/:id', (req, res) {
return req.parseBody().then((_) { return req.parseBody().then((_) async {
return this.modify( return await this.modify(
parseId<Id>(req.params['id']), parseId<Id>(req.params['id']),
req.bodyAsMap as Data, await readData(req, res),
mergeMap([ mergeMap([
{'query': req.queryParameters}, {'query': req.queryParameters},
restProvider, restProvider,
@ -273,10 +294,10 @@ class Service<Id, Data> extends Routable {
Middleware updateMiddleware = Middleware updateMiddleware =
getAnnotation<Middleware>(service.update, app.container.reflector); getAnnotation<Middleware>(service.update, app.container.reflector);
post('/:id', (req, res) { post('/:id', (req, res) {
return req.parseBody().then((_) { return req.parseBody().then((_) async {
return this.update( return await this.update(
parseId<Id>(req.params['id']), parseId<Id>(req.params['id']),
req.bodyAsMap as Data, await readData(req, res),
mergeMap([ mergeMap([
{'query': req.queryParameters}, {'query': req.queryParameters},
restProvider, restProvider,
@ -289,10 +310,10 @@ class Service<Id, Data> extends Routable {
..addAll( ..addAll(
(updateMiddleware == null) ? [] : updateMiddleware.handlers)); (updateMiddleware == null) ? [] : updateMiddleware.handlers));
put('/:id', (req, res) { put('/:id', (req, res) {
return req.parseBody().then((_) { return req.parseBody().then((_) async {
return this.update( return await this.update(
parseId<Id>(req.params['id']), parseId<Id>(req.params['id']),
req.bodyAsMap as Data, await readData(req, res),
mergeMap([ mergeMap([
{'query': req.queryParameters}, {'query': req.queryParameters},
restProvider, restProvider,