unnecessary new/const removal
This commit is contained in:
parent
1ed6736257
commit
e57de0bd04
58 changed files with 473 additions and 491 deletions
|
@ -5,6 +5,7 @@ handlers to run, even after the response was closed.
|
|||
* Call `RequestContext.close` in `Driver.sendResponse`.
|
||||
* AngelConfigurer is now `FutureOr<void>`, instead of just `FutureOr`.
|
||||
* Use a `Container.has<Stopwatch>` check in `Driver.sendResponse`.
|
||||
* Remove unnecessary `new` and `const`.
|
||||
|
||||
# 2.0.0
|
||||
* Angel 2! :angel: :rocket:
|
||||
|
@ -124,7 +125,7 @@ stable, there'll be a conversion, perhaps.
|
|||
|
||||
- All calls to `Service.parseId` are now affixed with the `<Id>` argument.
|
||||
- Added `uri` getter to `AngelHttp`.
|
||||
- The default for `parseQuery` now wraps query parameters in `new Map<String, dynamic>.from`.
|
||||
- The default for `parseQuery` now wraps query parameters in `Map<String, dynamic>.from`.
|
||||
This resolves a bug in `package:angel_validate`.
|
||||
|
||||
# 2.0.0-alpha.9
|
||||
|
|
|
@ -13,7 +13,7 @@ import 'package:angel_container/mirrors.dart';
|
|||
import 'package:angel_framework/angel_framework.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
|
||||
// Index route. Returns JSON.
|
||||
app.get('/', (req, res) => res.write('Welcome to Angel!'));
|
||||
|
@ -43,12 +43,12 @@ main() async {
|
|||
|
||||
// Simple fallback to throw a 404 on unknown paths.
|
||||
app.fallback((req, res) {
|
||||
throw new AngelHttpException.notFound(
|
||||
throw AngelHttpException.notFound(
|
||||
message: 'Unknown path: "${req.uri.path}"',
|
||||
);
|
||||
});
|
||||
|
||||
var http = new AngelHttp(app);
|
||||
var http = AngelHttp(app);
|
||||
var server = await http.startServer('127.0.0.1', 3000);
|
||||
var url = 'http://${server.address.address}:${server.port}';
|
||||
print('Listening at $url');
|
||||
|
|
|
@ -5,3 +5,5 @@ analyzer:
|
|||
linter:
|
||||
rules:
|
||||
- avoid_slow_async_io
|
||||
- unnecessary_const
|
||||
- unnecessary_new
|
|
@ -6,8 +6,8 @@ import 'package:angel_framework/http.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel(reflector: MirrorsReflector())
|
||||
..logger = (new Logger('angel')
|
||||
var app = Angel(reflector: MirrorsReflector())
|
||||
..logger = (Logger('angel')
|
||||
..onRecord.listen((rec) {
|
||||
print(rec);
|
||||
if (rec.error != null) print(rec.error);
|
||||
|
@ -16,9 +16,9 @@ main() async {
|
|||
..encoders.addAll({'gzip': gzip.encoder});
|
||||
|
||||
app.fallback(
|
||||
(req, res) => new Future.error('Throwing just because I feel like!'));
|
||||
(req, res) => Future.error('Throwing just because I feel like!'));
|
||||
|
||||
var http = new AngelHttp(app);
|
||||
var http = AngelHttp(app);
|
||||
var server = await http.startServer('127.0.0.1', 3000);
|
||||
var url = 'http://${server.address.address}:${server.port}';
|
||||
print('Listening at $url');
|
||||
|
|
|
@ -6,15 +6,15 @@ import 'package:file/local.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel();
|
||||
app.logger = new Logger('angel')
|
||||
var app = Angel();
|
||||
app.logger = Logger('angel')
|
||||
..onRecord.listen((rec) {
|
||||
print(rec);
|
||||
if (rec.error != null) print(rec.error);
|
||||
if (rec.stackTrace != null) print(rec.stackTrace);
|
||||
});
|
||||
|
||||
var publicDir = new Directory('example/public');
|
||||
var publicDir = Directory('example/public');
|
||||
var indexHtml =
|
||||
const LocalFileSystem().file(publicDir.uri.resolve('body_parsing.html'));
|
||||
|
||||
|
@ -22,7 +22,7 @@ main() async {
|
|||
|
||||
app.post('/', (req, res) => req.parseBody().then((_) => req.bodyAsMap));
|
||||
|
||||
var ctx = new SecurityContext()
|
||||
var ctx = SecurityContext()
|
||||
..useCertificateChain('dev.pem')
|
||||
..usePrivateKey('dev.key', password: 'dartdart');
|
||||
|
||||
|
@ -35,8 +35,8 @@ main() async {
|
|||
st);
|
||||
}
|
||||
|
||||
var http1 = new AngelHttp(app);
|
||||
var http2 = new AngelHttp2(app, ctx);
|
||||
var http1 = AngelHttp(app);
|
||||
var http2 = AngelHttp2(app, ctx);
|
||||
|
||||
// HTTP/1.x requests will fallback to `AngelHttp`
|
||||
http2.onHttp1.listen(http1.handleRequest);
|
||||
|
|
|
@ -6,19 +6,19 @@ import 'package:logging/logging.dart';
|
|||
import 'common.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel()
|
||||
var app = Angel()
|
||||
..encoders.addAll({
|
||||
'gzip': gzip.encoder,
|
||||
'deflate': zlib.encoder,
|
||||
});
|
||||
app.logger = new Logger('angel')..onRecord.listen(dumpError);
|
||||
app.logger = Logger('angel')..onRecord.listen(dumpError);
|
||||
|
||||
app.get('/', (req, res) => 'Hello HTTP/2!!!');
|
||||
|
||||
app.fallback((req, res) => throw new AngelHttpException.notFound(
|
||||
app.fallback((req, res) => throw AngelHttpException.notFound(
|
||||
message: 'No file exists at ${req.uri}'));
|
||||
|
||||
var ctx = new SecurityContext()
|
||||
var ctx = SecurityContext()
|
||||
..useCertificateChain('dev.pem')
|
||||
..usePrivateKey('dev.key', password: 'dartdart');
|
||||
|
||||
|
@ -32,8 +32,8 @@ main() async {
|
|||
);
|
||||
}
|
||||
|
||||
var http1 = new AngelHttp(app);
|
||||
var http2 = new AngelHttp2(app, ctx);
|
||||
var http1 = AngelHttp(app);
|
||||
var http2 = AngelHttp2(app, ctx);
|
||||
|
||||
// HTTP/1.x requests will fallback to `AngelHttp`
|
||||
http2.onHttp1.listen(http1.handleRequest);
|
||||
|
|
|
@ -6,15 +6,15 @@ import 'package:file/local.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel();
|
||||
app.logger = new Logger('angel')
|
||||
var app = Angel();
|
||||
app.logger = Logger('angel')
|
||||
..onRecord.listen((rec) {
|
||||
print(rec);
|
||||
if (rec.error != null) print(rec.error);
|
||||
if (rec.stackTrace != null) print(rec.stackTrace);
|
||||
});
|
||||
|
||||
var publicDir = new Directory('example/http2/public');
|
||||
var publicDir = Directory('example/http2/public');
|
||||
var indexHtml =
|
||||
const LocalFileSystem().file(publicDir.uri.resolve('index.html'));
|
||||
var styleCss =
|
||||
|
@ -38,7 +38,7 @@ main() async {
|
|||
}
|
||||
});
|
||||
|
||||
var ctx = new SecurityContext()
|
||||
var ctx = SecurityContext()
|
||||
..useCertificateChain('dev.pem')
|
||||
..usePrivateKey('dev.key', password: 'dartdart');
|
||||
|
||||
|
@ -51,8 +51,8 @@ main() async {
|
|||
st);
|
||||
}
|
||||
|
||||
var http1 = new AngelHttp(app);
|
||||
var http2 = new AngelHttp2(app, ctx);
|
||||
var http1 = AngelHttp(app);
|
||||
var http2 = AngelHttp2(app, ctx);
|
||||
|
||||
// HTTP/1.x requests will fallback to `AngelHttp`
|
||||
http2.onHttp1.listen(http1.handleRequest);
|
||||
|
|
|
@ -6,8 +6,8 @@ import 'package:angel_framework/http.dart';
|
|||
|
||||
main() async {
|
||||
int x = 0;
|
||||
var c = new Completer();
|
||||
var exit = new ReceivePort();
|
||||
var c = Completer();
|
||||
var exit = ReceivePort();
|
||||
List<Isolate> isolates = [];
|
||||
|
||||
exit.listen((_) {
|
||||
|
@ -31,9 +31,9 @@ main() async {
|
|||
}
|
||||
|
||||
serverMain(_) async {
|
||||
var app = new Angel();
|
||||
var app = Angel();
|
||||
var http =
|
||||
new AngelHttp.custom(app, startShared, useZone: false); // Run a cluster
|
||||
AngelHttp.custom(app, startShared, useZone: false); // Run a cluster
|
||||
|
||||
app.get('/', (req, res) {
|
||||
return res.serialize({
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:angel_framework/angel_framework.dart';
|
|||
import 'package:angel_framework/http.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel();
|
||||
var http = new AngelHttp(app);
|
||||
var app = Angel();
|
||||
var http = AngelHttp(app);
|
||||
|
||||
app.fallback((req, res) {
|
||||
res.statusCode = 304;
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:angel_framework/angel_framework.dart';
|
|||
import 'package:angel_framework/http.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
|
||||
app.viewGenerator = (name, [data]) async =>
|
||||
'View generator invoked with name $name and data: $data';
|
||||
|
@ -11,7 +11,7 @@ main() async {
|
|||
// Index route. Returns JSON.
|
||||
app.get('/', (req, res) => res.render('index', {'foo': 'bar'}));
|
||||
|
||||
var http = new AngelHttp(app);
|
||||
var http = AngelHttp(app);
|
||||
var server = await http.startServer('127.0.0.1', 3000);
|
||||
var url = 'http://${server.address.address}:${server.port}';
|
||||
print('Listening at $url');
|
||||
|
|
|
@ -30,30 +30,30 @@ class AnonymousService<Id, Data> extends Service<Id, Data> {
|
|||
}
|
||||
|
||||
@override
|
||||
index([Map<String, dynamic> params]) => new Future.sync(
|
||||
() => _index != null ? _index(params) : super.index(params));
|
||||
index([Map<String, dynamic> params]) =>
|
||||
Future.sync(() => _index != null ? _index(params) : super.index(params));
|
||||
|
||||
@override
|
||||
read(Id id, [Map<String, dynamic> params]) => new Future.sync(
|
||||
read(Id id, [Map<String, dynamic> params]) => Future.sync(
|
||||
() => _read != null ? _read(id, params) : super.read(id, params));
|
||||
|
||||
@override
|
||||
create(Data data, [Map<String, dynamic> params]) => new Future.sync(() =>
|
||||
create(Data data, [Map<String, dynamic> params]) => Future.sync(() =>
|
||||
_create != null ? _create(data, params) : super.create(data, params));
|
||||
|
||||
@override
|
||||
modify(Id id, Data data, [Map<String, dynamic> params]) =>
|
||||
new Future.sync(() => _modify != null
|
||||
Future.sync(() => _modify != null
|
||||
? _modify(id, data, params)
|
||||
: super.modify(id, data, params));
|
||||
|
||||
@override
|
||||
update(Id id, Data data, [Map<String, dynamic> params]) =>
|
||||
new Future.sync(() => _update != null
|
||||
Future.sync(() => _update != null
|
||||
? _update(id, data, params)
|
||||
: super.update(id, data, params));
|
||||
|
||||
@override
|
||||
remove(Id id, [Map<String, dynamic> params]) => new Future.sync(
|
||||
remove(Id id, [Map<String, dynamic> params]) => Future.sync(
|
||||
() => _remove != null ? _remove(id, params) : super.remove(id, params));
|
||||
}
|
||||
|
|
|
@ -40,11 +40,10 @@ class Controller {
|
|||
Expose exposeDecl = findExpose(app.container.reflector);
|
||||
|
||||
if (exposeDecl == null) {
|
||||
throw new Exception(
|
||||
"All controllers must carry an @Expose() declaration.");
|
||||
throw Exception("All controllers must carry an @Expose() declaration.");
|
||||
}
|
||||
|
||||
var routable = new Routable();
|
||||
var routable = Routable();
|
||||
app.mount(exposeDecl.path, routable);
|
||||
var typeMirror = app.container.reflector.reflectType(this.runtimeType);
|
||||
String name =
|
||||
|
@ -60,7 +59,7 @@ class Controller {
|
|||
final routeBuilder = _routeBuilder(instanceMirror, routable, handlers);
|
||||
classMirror.declarations.forEach(routeBuilder);
|
||||
configureRoutes(routable);
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
void Function(ReflectedDeclaration) _routeBuilder(
|
||||
|
|
|
@ -57,7 +57,7 @@ abstract class Driver<
|
|||
|
||||
/// Shuts down the underlying server.
|
||||
Future<Server> close() {
|
||||
if (_closed) return new Future.value(_server);
|
||||
if (_closed) return Future.value(_server);
|
||||
_closed = true;
|
||||
_sub?.cancel();
|
||||
return app.close().then((_) =>
|
||||
|
@ -102,8 +102,8 @@ abstract class Driver<
|
|||
var r = app.optimizedRouter;
|
||||
var resolved =
|
||||
r.resolveAbsolute(path, method: req.method, strip: false);
|
||||
var pipeline = new MiddlewarePipeline<RequestHandler>(resolved);
|
||||
return new Tuple4(
|
||||
var pipeline = MiddlewarePipeline<RequestHandler>(resolved);
|
||||
return Tuple4(
|
||||
pipeline.handlers,
|
||||
resolved.fold<Map<String, dynamic>>(
|
||||
<String, dynamic>{}, (out, r) => out..addAll(r.allParams)),
|
||||
|
@ -132,8 +132,7 @@ abstract class Driver<
|
|||
..registerSingleton<ParseResult>(tuple.item3);
|
||||
|
||||
if (!app.environment.isProduction && app.logger != null) {
|
||||
req.container
|
||||
.registerSingleton<Stopwatch>(new Stopwatch()..start());
|
||||
req.container.registerSingleton<Stopwatch>(Stopwatch()..start());
|
||||
}
|
||||
|
||||
return runPipeline(it, req, res, app)
|
||||
|
@ -151,9 +150,9 @@ abstract class Driver<
|
|||
|
||||
return f.catchError((e, StackTrace st) {
|
||||
if (e is FormatException)
|
||||
throw new AngelHttpException.badRequest(message: e.message)
|
||||
throw AngelHttpException.badRequest(message: e.message)
|
||||
..stackTrace = st;
|
||||
throw new AngelHttpException(e,
|
||||
throw AngelHttpException(e,
|
||||
stackTrace: st,
|
||||
statusCode: 500,
|
||||
message: e?.toString() ?? '500 Internal Server Error');
|
||||
|
@ -163,8 +162,7 @@ abstract class Driver<
|
|||
|
||||
if (app.logger != null) {
|
||||
var error = e.error ?? e;
|
||||
var trace =
|
||||
new Trace.from(e.stackTrace ?? StackTrace.current).terse;
|
||||
var trace = Trace.from(e.stackTrace ?? StackTrace.current).terse;
|
||||
app.logger.severe(e.message ?? e.toString(), error, trace);
|
||||
}
|
||||
|
||||
|
@ -172,7 +170,7 @@ abstract class Driver<
|
|||
e, e.stackTrace ?? st, req, res, request, response);
|
||||
});
|
||||
} else {
|
||||
var zoneSpec = new ZoneSpecification(
|
||||
var zoneSpec = ZoneSpecification(
|
||||
print: (self, parent, zone, line) {
|
||||
if (app.logger != null)
|
||||
app.logger.info(line);
|
||||
|
@ -180,18 +178,17 @@ abstract class Driver<
|
|||
parent.print(zone, line);
|
||||
},
|
||||
handleUncaughtError: (self, parent, zone, error, stackTrace) {
|
||||
var trace =
|
||||
new Trace.from(stackTrace ?? StackTrace.current).terse;
|
||||
var trace = Trace.from(stackTrace ?? StackTrace.current).terse;
|
||||
|
||||
return new Future(() {
|
||||
return Future(() {
|
||||
AngelHttpException e;
|
||||
|
||||
if (error is FormatException) {
|
||||
e = new AngelHttpException.badRequest(message: error.message);
|
||||
e = AngelHttpException.badRequest(message: error.message);
|
||||
} else if (error is AngelHttpException) {
|
||||
e = error;
|
||||
} else {
|
||||
e = new AngelHttpException(error,
|
||||
e = AngelHttpException(error,
|
||||
stackTrace: stackTrace,
|
||||
message:
|
||||
error?.toString() ?? '500 Internal Server Error');
|
||||
|
@ -204,7 +201,7 @@ abstract class Driver<
|
|||
return handleAngelHttpException(
|
||||
e, trace, req, res, request, response);
|
||||
}).catchError((e, StackTrace st) {
|
||||
var trace = new Trace.from(st ?? StackTrace.current).terse;
|
||||
var trace = Trace.from(st ?? StackTrace.current).terse;
|
||||
closeResponse(response);
|
||||
// Ideally, we won't be in a position where an absolutely fatal error occurs,
|
||||
// but if so, we'll need to log it.
|
||||
|
@ -263,11 +260,11 @@ abstract class Driver<
|
|||
Future handleError;
|
||||
|
||||
if (!res.isOpen)
|
||||
handleError = new Future.value();
|
||||
handleError = Future.value();
|
||||
else {
|
||||
res.statusCode = e.statusCode;
|
||||
handleError =
|
||||
new Future.sync(() => app.errorHandler(e, req, res)).then((result) {
|
||||
Future.sync(() => app.errorHandler(e, req, res)).then((result) {
|
||||
return app.executeHandler(result, req, res).then((_) => res.close());
|
||||
});
|
||||
}
|
||||
|
@ -294,7 +291,7 @@ abstract class Driver<
|
|||
if (!res.isBuffered) return res.close().then(_cleanup);
|
||||
|
||||
Future finalizers = ignoreFinalizers == true
|
||||
? new Future.value()
|
||||
? Future.value()
|
||||
: Future.forEach(app.responseFinalizers, (f) => f(req, res));
|
||||
|
||||
return finalizers.then((_) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
/// A constant instance of [AngelEnv].
|
||||
const AngelEnvironment angelEnv = const AngelEnvironment();
|
||||
const AngelEnvironment angelEnv = AngelEnvironment();
|
||||
|
||||
/// Queries the environment's `ANGEL_ENV` value.
|
||||
class AngelEnvironment {
|
||||
|
|
|
@ -19,29 +19,29 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
final T inner;
|
||||
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeIndexed =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeRead =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeCreated =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeModified =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeUpdated =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> beforeRemoved =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterIndexed =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterRead =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterCreated =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterModified =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterUpdated =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
final HookedServiceEventDispatcher<Id, Data, T> afterRemoved =
|
||||
new HookedServiceEventDispatcher<Id, Data, T>();
|
||||
HookedServiceEventDispatcher<Id, Data, T>();
|
||||
|
||||
HookedService(this.inner) {
|
||||
// Clone app instance
|
||||
|
@ -89,7 +89,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
afterUpdated._close();
|
||||
afterRemoved._close();
|
||||
inner.close();
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
/// Adds hooks to this instance.
|
||||
|
@ -130,7 +130,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
}
|
||||
|
||||
List<RequestHandler> get bootstrappers =>
|
||||
new List<RequestHandler>.from(super.bootstrappers)
|
||||
List<RequestHandler>.from(super.bootstrappers)
|
||||
..add((RequestContext req, ResponseContext res) {
|
||||
req.serviceParams
|
||||
..['__requestctx'] = req
|
||||
|
@ -160,7 +160,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
case HookedServiceEvent.removed:
|
||||
return beforeRemoved;
|
||||
default:
|
||||
throw new ArgumentError('Invalid service method: ${name}');
|
||||
throw ArgumentError('Invalid service method: ${name}');
|
||||
}
|
||||
}).forEach((HookedServiceEventDispatcher<Id, Data, T> dispatcher) =>
|
||||
dispatcher.listen(listener));
|
||||
|
@ -184,7 +184,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
case HookedServiceEvent.removed:
|
||||
return afterRemoved;
|
||||
default:
|
||||
throw new ArgumentError('Invalid service method: ${name}');
|
||||
throw ArgumentError('Invalid service method: ${name}');
|
||||
}
|
||||
}).forEach((HookedServiceEventDispatcher<Id, Data, T> dispatcher) =>
|
||||
dispatcher.listen(listener));
|
||||
|
@ -216,7 +216,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent<Id, Data, T>> beforeAllStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
var ctrl = StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
_ctrl.add(ctrl);
|
||||
before(HookedServiceEvent.all, ctrl.add);
|
||||
return ctrl.stream;
|
||||
|
@ -228,7 +228,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent<Id, Data, T>> afterAllStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
var ctrl = StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
_ctrl.add(ctrl);
|
||||
before(HookedServiceEvent.all, ctrl.add);
|
||||
return ctrl.stream;
|
||||
|
@ -241,7 +241,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
/// callback.
|
||||
Stream<HookedServiceEvent<Id, Data, T>> beforeStream(
|
||||
Iterable<String> eventNames) {
|
||||
var ctrl = new StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
var ctrl = StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
_ctrl.add(ctrl);
|
||||
before(eventNames, ctrl.add);
|
||||
return ctrl.stream;
|
||||
|
@ -254,7 +254,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
/// callback.
|
||||
Stream<HookedServiceEvent<Id, Data, T>> afterStream(
|
||||
Iterable<String> eventNames) {
|
||||
var ctrl = new StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
var ctrl = StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
_ctrl.add(ctrl);
|
||||
after(eventNames, ctrl.add);
|
||||
return ctrl.stream;
|
||||
|
@ -271,13 +271,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<List<Data>> index([Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeIndexed
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.indexed,
|
||||
params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterIndexed
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.indexed,
|
||||
params: params, result: before.result))
|
||||
.then((after) => after.result as List<Data>);
|
||||
|
@ -285,7 +285,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.index(params).then((result) {
|
||||
return afterIndexed
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.indexed,
|
||||
params: params, result: result))
|
||||
.then((after) => after.result as List<Data>);
|
||||
|
@ -297,13 +297,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<Data> read(Id id, [Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeRead
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.read,
|
||||
id: id, params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterRead
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.read,
|
||||
id: id, params: params, result: before.result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -311,7 +311,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.read(id, params).then((result) {
|
||||
return afterRead
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.read,
|
||||
id: id, params: params, result: result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -323,13 +323,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<Data> create(Data data, [Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeCreated
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.created,
|
||||
data: data, params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterCreated
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.created,
|
||||
data: before.data, params: params, result: before.result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -337,7 +337,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.create(before.data, params).then((result) {
|
||||
return afterCreated
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.created,
|
||||
data: before.data, params: params, result: result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -349,13 +349,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<Data> modify(Id id, Data data, [Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeModified
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.modified,
|
||||
id: id, data: data, params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterModified
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.modified,
|
||||
id: id,
|
||||
data: before.data,
|
||||
|
@ -366,7 +366,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.modify(id, before.data, params).then((result) {
|
||||
return afterModified
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.created,
|
||||
id: id, data: before.data, params: params, result: result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -378,13 +378,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<Data> update(Id id, Data data, [Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeUpdated
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.updated,
|
||||
id: id, data: data, params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterUpdated
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.updated,
|
||||
id: id,
|
||||
data: before.data,
|
||||
|
@ -395,7 +395,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.update(id, before.data, params).then((result) {
|
||||
return afterUpdated
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.updated,
|
||||
id: id, data: before.data, params: params, result: result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -407,13 +407,13 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
Future<Data> remove(Id id, [Map<String, dynamic> _params]) {
|
||||
var params = _stripReq(_params);
|
||||
return beforeRemoved
|
||||
._emit(new HookedServiceEvent(false, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(false, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.removed,
|
||||
id: id, params: params))
|
||||
.then((before) {
|
||||
if (before._canceled) {
|
||||
return afterRemoved
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.removed,
|
||||
id: id, params: params, result: before.result))
|
||||
.then((after) => after.result) as Data;
|
||||
|
@ -421,7 +421,7 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
|
||||
return inner.remove(id, params).then((result) {
|
||||
return afterRemoved
|
||||
._emit(new HookedServiceEvent(true, _getRequest(_params),
|
||||
._emit(HookedServiceEvent(true, _getRequest(_params),
|
||||
_getResponse(_params), inner, HookedServiceEvent.removed,
|
||||
id: id, params: params, result: result))
|
||||
.then((after) => after.result as Data);
|
||||
|
@ -455,11 +455,11 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
dispatcher = afterRemoved;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentError("Invalid service event name: '$eventName'");
|
||||
throw ArgumentError("Invalid service event name: '$eventName'");
|
||||
}
|
||||
|
||||
var ev =
|
||||
new HookedServiceEvent<Id, Data, T>(true, null, null, inner, eventName);
|
||||
HookedServiceEvent<Id, Data, T>(true, null, null, inner, eventName);
|
||||
return fireEvent(dispatcher, ev, callback);
|
||||
}
|
||||
|
||||
|
@ -470,8 +470,8 @@ class HookedService<Id, Data, T extends Service<Id, Data>>
|
|||
[HookedServiceEventListener<Id, Data, T> callback]) {
|
||||
Future f;
|
||||
if (callback != null && event?._canceled != true)
|
||||
f = new Future.sync(() => callback(event));
|
||||
f ??= new Future.value();
|
||||
f = Future.sync(() => callback(event));
|
||||
f ??= Future.value();
|
||||
return f.then((_) => dispatcher._emit(event));
|
||||
}
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ class HookedServiceEvent<Id, Data, T extends Service<Id, Data>> {
|
|||
static const String updated = 'updated';
|
||||
static const String removed = 'removed';
|
||||
|
||||
static const List<String> all = const [
|
||||
static const List<String> all = [
|
||||
indexed,
|
||||
read,
|
||||
created,
|
||||
|
@ -558,14 +558,14 @@ class HookedServiceEventDispatcher<Id, Data, T extends Service<Id, Data>> {
|
|||
Future<HookedServiceEvent<Id, Data, T>> _emit(
|
||||
HookedServiceEvent<Id, Data, T> event) {
|
||||
if (event?._canceled == true || event == null || listeners.isEmpty)
|
||||
return new Future.value(event);
|
||||
return Future.value(event);
|
||||
|
||||
var f = new Future<HookedServiceEvent<Id, Data, T>>.value(event);
|
||||
var f = Future<HookedServiceEvent<Id, Data, T>>.value(event);
|
||||
|
||||
for (var listener in listeners) {
|
||||
f = f.then((event) {
|
||||
if (event._canceled) return event;
|
||||
return new Future.sync(() => listener(event)).then((_) => event);
|
||||
return Future.sync(() => listener(event)).then((_) => event);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@ class HookedServiceEventDispatcher<Id, Data, T extends Service<Id, Data>> {
|
|||
/// *NOTE*: Callbacks on the returned [Stream] cannot be guaranteed to run before other [listeners].
|
||||
/// Use this only if you need a read-only stream of events.
|
||||
Stream<HookedServiceEvent<Id, Data, T>> asStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
var ctrl = StreamController<HookedServiceEvent<Id, Data, T>>();
|
||||
_ctrl.add(ctrl);
|
||||
listen(ctrl.add);
|
||||
return ctrl.stream;
|
||||
|
|
|
@ -48,7 +48,7 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req,
|
|||
else if (injection.optional.contains(requirement))
|
||||
return null;
|
||||
else if (throwOnUnresolved) {
|
||||
throw new ArgumentError(
|
||||
throw ArgumentError(
|
||||
"Cannot resolve parameter '$requirement' within handler.");
|
||||
}
|
||||
} else if (requirement is List &&
|
||||
|
@ -76,7 +76,7 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req,
|
|||
|
||||
return await container.make(requirement);
|
||||
} else if (throwOnUnresolved) {
|
||||
throw new ArgumentError(
|
||||
throw ArgumentError(
|
||||
'$requirement cannot be injected into a request handler.');
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +97,7 @@ RequestHandler handleContained(Function handler, InjectionRequest injection,
|
|||
return (RequestContext req, ResponseContext res) async {
|
||||
if (injection.parameters.isNotEmpty &&
|
||||
injection.parameters.values.any((p) => p.match != null) &&
|
||||
!suitableForInjection(req, res, injection))
|
||||
return new Future.value(true);
|
||||
!suitableForInjection(req, res, injection)) return Future.value(true);
|
||||
|
||||
List args = [];
|
||||
|
||||
|
@ -109,7 +108,7 @@ RequestHandler handleContained(Function handler, InjectionRequest injection,
|
|||
}
|
||||
|
||||
for (var entry in injection.named.entries) {
|
||||
var name = new Symbol(entry.key);
|
||||
var name = Symbol(entry.key);
|
||||
named[name] = await resolveInjection(
|
||||
[entry.key, entry.value], injection, req, res, false, container);
|
||||
}
|
||||
|
@ -153,7 +152,7 @@ class InjectionRequest {
|
|||
|
||||
/// Predetermines what needs to be injected for a handler to run.
|
||||
InjectionRequest preInject(Function handler, Reflector reflector) {
|
||||
var injection = new InjectionRequest();
|
||||
var injection = InjectionRequest();
|
||||
|
||||
var closureMirror = reflector.reflectFunction(handler);
|
||||
|
||||
|
@ -172,7 +171,7 @@ InjectionRequest preInject(Function handler, Reflector reflector) {
|
|||
?.reflectee as Parameter;
|
||||
//print(p);
|
||||
if (p != null) {
|
||||
injection.parameters[name] = new Parameter(
|
||||
injection.parameters[name] = Parameter(
|
||||
cookie: p.cookie,
|
||||
header: p.header,
|
||||
query: p.query,
|
||||
|
|
|
@ -49,11 +49,11 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
@override
|
||||
Future<List<Map<String, dynamic>>> index([Map<String, dynamic> params]) {
|
||||
if (allowQuery == false || params == null || params['query'] is! Map)
|
||||
return new Future.value(items);
|
||||
return Future.value(items);
|
||||
else {
|
||||
var query = params['query'] as Map;
|
||||
|
||||
return new Future.value(items.where((item) {
|
||||
return Future.value(items.where((item) {
|
||||
for (var key in query.keys) {
|
||||
if (!item.containsKey(key))
|
||||
return false;
|
||||
|
@ -67,8 +67,8 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
|
||||
@override
|
||||
Future<Map<String, dynamic>> read(String id, [Map<String, dynamic> params]) {
|
||||
return new Future.value(items.firstWhere(_matchesId(id),
|
||||
orElse: () => throw new AngelHttpException.notFound(
|
||||
return Future.value(items.firstWhere(_matchesId(id),
|
||||
orElse: () => throw AngelHttpException.notFound(
|
||||
message: 'No record found for ID $id')));
|
||||
}
|
||||
|
||||
|
@ -76,11 +76,11 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
|
||||
[Map<String, dynamic> params]) {
|
||||
if (data is! Map)
|
||||
throw new AngelHttpException.badRequest(
|
||||
throw AngelHttpException.badRequest(
|
||||
message:
|
||||
'MapService does not support `create` with ${data.runtimeType}.');
|
||||
var now = new DateTime.now().toIso8601String();
|
||||
var result = new Map<String, dynamic>.from(data);
|
||||
var now = DateTime.now().toIso8601String();
|
||||
var result = Map<String, dynamic>.from(data);
|
||||
|
||||
if (autoIdAndDateFields == true) {
|
||||
result
|
||||
|
@ -89,14 +89,14 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] = now;
|
||||
}
|
||||
items.add(result);
|
||||
return new Future.value(result);
|
||||
return Future.value(result);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> modify(String id, Map<String, dynamic> data,
|
||||
[Map<String, dynamic> params]) {
|
||||
if (data is! Map)
|
||||
throw new AngelHttpException.badRequest(
|
||||
throw AngelHttpException.badRequest(
|
||||
message:
|
||||
'MapService does not support `modify` with ${data.runtimeType}.');
|
||||
if (!items.any(_matchesId(id))) return create(data, params);
|
||||
|
@ -104,13 +104,13 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
return read(id).then((item) {
|
||||
var idx = items.indexOf(item);
|
||||
if (idx < 0) return create(data, params);
|
||||
var result = new Map<String, dynamic>.from(item)..addAll(data);
|
||||
var result = Map<String, dynamic>.from(item)..addAll(data);
|
||||
|
||||
if (autoIdAndDateFields == true)
|
||||
result
|
||||
..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] =
|
||||
new DateTime.now().toIso8601String();
|
||||
return new Future.value(items[idx] = result);
|
||||
DateTime.now().toIso8601String();
|
||||
return Future.value(items[idx] = result);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -118,27 +118,27 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
Future<Map<String, dynamic>> update(String id, Map<String, dynamic> data,
|
||||
[Map<String, dynamic> params]) {
|
||||
if (data is! Map)
|
||||
throw new AngelHttpException.badRequest(
|
||||
throw AngelHttpException.badRequest(
|
||||
message:
|
||||
'MapService does not support `update` with ${data.runtimeType}.');
|
||||
if (!items.any(_matchesId(id))) return create(data, params);
|
||||
|
||||
return read(id).then((old) {
|
||||
if (!items.remove(old))
|
||||
throw new AngelHttpException.notFound(
|
||||
throw AngelHttpException.notFound(
|
||||
message: 'No record found for ID $id');
|
||||
|
||||
var result = new Map<String, dynamic>.from(data);
|
||||
var result = Map<String, dynamic>.from(data);
|
||||
if (autoIdAndDateFields == true) {
|
||||
result
|
||||
..['id'] = id?.toString()
|
||||
..[autoSnakeCaseNames == false ? 'createdAt' : 'created_at'] =
|
||||
old[autoSnakeCaseNames == false ? 'createdAt' : 'created_at']
|
||||
..[autoSnakeCaseNames == false ? 'updatedAt' : 'updated_at'] =
|
||||
new DateTime.now().toIso8601String();
|
||||
DateTime.now().toIso8601String();
|
||||
}
|
||||
items.add(result);
|
||||
return new Future.value(result);
|
||||
return Future.value(result);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
message: 'Clients are not allowed to delete all items.');
|
||||
} else {
|
||||
items.clear();
|
||||
return new Future.value({});
|
||||
return Future.value({});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ class MapService extends Service<String, Map<String, dynamic>> {
|
|||
if (items.remove(result))
|
||||
return result;
|
||||
else
|
||||
throw new AngelHttpException.notFound(
|
||||
throw AngelHttpException.notFound(
|
||||
message: 'No record found for ID $id');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -71,17 +71,16 @@ class Parameter {
|
|||
/// Returns an error that can be thrown when the parameter is not present.
|
||||
get error {
|
||||
if (cookie?.isNotEmpty == true)
|
||||
return new AngelHttpException.badRequest(
|
||||
return AngelHttpException.badRequest(
|
||||
message: 'Missing required cookie "$cookie".');
|
||||
if (header?.isNotEmpty == true)
|
||||
return new AngelHttpException.badRequest(
|
||||
return AngelHttpException.badRequest(
|
||||
message: 'Missing required header "$header".');
|
||||
if (query?.isNotEmpty == true)
|
||||
return new AngelHttpException.badRequest(
|
||||
return AngelHttpException.badRequest(
|
||||
message: 'Missing required query parameter "$query".');
|
||||
if (session?.isNotEmpty == true)
|
||||
return new StateError(
|
||||
'Session does not contain required key "$session".');
|
||||
return StateError('Session does not contain required key "$session".');
|
||||
}
|
||||
|
||||
/// Obtains a value for this parameter from a [RequestContext].
|
||||
|
|
|
@ -76,7 +76,7 @@ abstract class RequestContext<RawRequest> {
|
|||
|
||||
/// The content type of an incoming request.
|
||||
MediaType get contentType =>
|
||||
_contentType ??= new MediaType.parse(headers.contentType.toString());
|
||||
_contentType ??= MediaType.parse(headers.contentType.toString());
|
||||
|
||||
/// The URL parameters extracted from the request URI.
|
||||
Map<String, dynamic> params = <String, dynamic>{};
|
||||
|
@ -110,9 +110,9 @@ abstract class RequestContext<RawRequest> {
|
|||
/// Note that [parseBody] must be called first.
|
||||
Map<String, dynamic> get bodyAsMap {
|
||||
if (!hasParsedBody) {
|
||||
throw new StateError('The request body has not been parsed yet.');
|
||||
throw StateError('The request body has not been parsed yet.');
|
||||
} else if (_bodyFields == null) {
|
||||
throw new StateError('The request body, $_bodyObject, is not a Map.');
|
||||
throw StateError('The request body, $_bodyObject, is not a Map.');
|
||||
}
|
||||
|
||||
return _bodyFields;
|
||||
|
@ -128,9 +128,9 @@ abstract class RequestContext<RawRequest> {
|
|||
/// Note that [parseBody] must be called first.
|
||||
List get bodyAsList {
|
||||
if (!hasParsedBody) {
|
||||
throw new StateError('The request body has not been parsed yet.');
|
||||
throw StateError('The request body has not been parsed yet.');
|
||||
} else if (_bodyList == null) {
|
||||
throw new StateError('The request body, $_bodyObject, is not a List.');
|
||||
throw StateError('The request body, $_bodyObject, is not a List.');
|
||||
}
|
||||
|
||||
return _bodyList;
|
||||
|
@ -146,7 +146,7 @@ abstract class RequestContext<RawRequest> {
|
|||
/// Note that [parseBody] must be called first.
|
||||
Object get bodyAsObject {
|
||||
if (!hasParsedBody) {
|
||||
throw new StateError('The request body has not been parsed yet.');
|
||||
throw StateError('The request body has not been parsed yet.');
|
||||
}
|
||||
|
||||
return _bodyObject;
|
||||
|
@ -172,7 +172,7 @@ abstract class RequestContext<RawRequest> {
|
|||
/// Note that [parseBody] must be called first.
|
||||
List<UploadedFile> get uploadedFiles {
|
||||
if (!hasParsedBody) {
|
||||
throw new StateError('The request body has not been parsed yet.');
|
||||
throw StateError('The request body has not been parsed yet.');
|
||||
}
|
||||
|
||||
return _uploadedFiles;
|
||||
|
@ -180,7 +180,7 @@ abstract class RequestContext<RawRequest> {
|
|||
|
||||
/// Returns a *mutable* map of the fields contained in the query.
|
||||
Map<String, dynamic> get queryParameters =>
|
||||
_queryParameters ??= new Map<String, dynamic>.from(uri.queryParameters);
|
||||
_queryParameters ??= Map<String, dynamic>.from(uri.queryParameters);
|
||||
|
||||
/// Returns the file extension of the requested path, if any.
|
||||
///
|
||||
|
@ -203,7 +203,7 @@ abstract class RequestContext<RawRequest> {
|
|||
|
||||
// Change to assert
|
||||
if (contentTypeString == null)
|
||||
throw new ArgumentError(
|
||||
throw ArgumentError(
|
||||
'RequestContext.accepts expects the `contentType` parameter to NOT be null.');
|
||||
|
||||
_acceptHeaderCache ??= headers.value('accept');
|
||||
|
@ -235,7 +235,7 @@ abstract class RequestContext<RawRequest> {
|
|||
await body.transform(encoding.decoder).join().then(json.decode);
|
||||
|
||||
if (parsed is Map) {
|
||||
_bodyFields = new Map<String, dynamic>.from(parsed);
|
||||
_bodyFields = Map<String, dynamic>.from(parsed);
|
||||
} else if (parsed is List) {
|
||||
_bodyList = parsed;
|
||||
}
|
||||
|
@ -246,12 +246,12 @@ abstract class RequestContext<RawRequest> {
|
|||
.transform(encoding.decoder)
|
||||
.join()
|
||||
.then((s) => Uri.splitQueryString(s, encoding: encoding));
|
||||
_bodyFields = new Map<String, dynamic>.from(parsed);
|
||||
_bodyFields = Map<String, dynamic>.from(parsed);
|
||||
} else if (contentType.type == 'multipart' &&
|
||||
contentType.subtype == 'form-data' &&
|
||||
contentType.parameters.containsKey('boundary')) {
|
||||
var boundary = contentType.parameters['boundary'];
|
||||
var transformer = new MimeMultipartTransformer(boundary);
|
||||
var transformer = MimeMultipartTransformer(boundary);
|
||||
var parts = body.transform(transformer).map((part) =>
|
||||
HttpMultipartFormData.parse(part, defaultEncoding: encoding));
|
||||
_bodyFields = {};
|
||||
|
@ -259,7 +259,7 @@ abstract class RequestContext<RawRequest> {
|
|||
|
||||
await for (var part in parts) {
|
||||
if (part.isBinary) {
|
||||
_uploadedFiles.add(new UploadedFile(part));
|
||||
_uploadedFiles.add(UploadedFile(part));
|
||||
} else if (part.isText &&
|
||||
part.contentDisposition.parameters.containsKey('name')) {
|
||||
// If there is no name, then don't parse it.
|
||||
|
@ -313,7 +313,7 @@ class UploadedFile {
|
|||
/// Returns [:null:] if not present.
|
||||
MediaType get contentType => _contentType ??= (formData.contentType == null
|
||||
? null
|
||||
: new MediaType.parse(formData.contentType.toString()));
|
||||
: MediaType.parse(formData.contentType.toString()));
|
||||
|
||||
/// The parsed [:Content-Transfer-Encoding:] header of the
|
||||
/// [:HttpMultipartFormData:]. This field is used to determine how to decode
|
||||
|
|
|
@ -14,14 +14,13 @@ import 'controller.dart';
|
|||
import 'request_context.dart';
|
||||
import 'server.dart' show Angel;
|
||||
|
||||
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
/// A convenience wrapper around an outgoing HTTP request.
|
||||
abstract class ResponseContext<RawResponse>
|
||||
implements StreamSink<List<int>>, StringSink {
|
||||
final Map properties = {};
|
||||
final CaseInsensitiveMap<String> _headers =
|
||||
new CaseInsensitiveMap<String>.from({
|
||||
final CaseInsensitiveMap<String> _headers = CaseInsensitiveMap<String>.from({
|
||||
'content-type': 'text/plain',
|
||||
'server': 'angel',
|
||||
});
|
||||
|
@ -52,7 +51,7 @@ abstract class ResponseContext<RawResponse>
|
|||
RequestContext get correspondingRequest;
|
||||
|
||||
@override
|
||||
Future get done => (_done ?? new Completer()).future;
|
||||
Future get done => (_done ?? Completer()).future;
|
||||
|
||||
/// Headers that will be sent to the user.
|
||||
///
|
||||
|
@ -124,9 +123,9 @@ abstract class ResponseContext<RawResponse>
|
|||
/// Gets or sets the content type to send back to a client.
|
||||
MediaType get contentType {
|
||||
try {
|
||||
return new MediaType.parse(headers['content-type']);
|
||||
return MediaType.parse(headers['content-type']);
|
||||
} catch (_) {
|
||||
return new MediaType('text', 'plain');
|
||||
return MediaType('text', 'plain');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,8 +134,7 @@ abstract class ResponseContext<RawResponse>
|
|||
headers['content-type'] = value.toString();
|
||||
}
|
||||
|
||||
static StateError closed() =>
|
||||
new StateError('Cannot modify a closed response.');
|
||||
static StateError closed() => StateError('Cannot modify a closed response.');
|
||||
|
||||
/// Sends a download as a response.
|
||||
Future<void> download(File file, {String filename}) async {
|
||||
|
@ -162,7 +160,7 @@ abstract class ResponseContext<RawResponse>
|
|||
}
|
||||
|
||||
if (_done?.isCompleted == false) _done.complete();
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
/// Serializes JSON to the response.
|
||||
|
@ -176,8 +174,7 @@ abstract class ResponseContext<RawResponse>
|
|||
Future<void> jsonp(value,
|
||||
{String callbackName = "callback", MediaType contentType}) {
|
||||
if (!isOpen) throw closed();
|
||||
this.contentType =
|
||||
contentType ?? new MediaType('application', 'javascript');
|
||||
this.contentType = contentType ?? MediaType('application', 'javascript');
|
||||
write("$callbackName(${serializer(value)})");
|
||||
return close();
|
||||
}
|
||||
|
@ -185,10 +182,10 @@ abstract class ResponseContext<RawResponse>
|
|||
/// Renders a view to the response stream, and closes the response.
|
||||
Future<void> render(String view, [Map<String, dynamic> data]) {
|
||||
if (!isOpen) throw closed();
|
||||
contentType = new MediaType('text', 'html', {'charset': 'utf-8'});
|
||||
contentType = MediaType('text', 'html', {'charset': 'utf-8'});
|
||||
return Future<String>.sync(() => app.viewGenerator(
|
||||
view,
|
||||
new Map<String, dynamic>.from(renderParams)
|
||||
Map<String, dynamic>.from(renderParams)
|
||||
..addAll(data ?? <String, dynamic>{}))).then((content) {
|
||||
write(content);
|
||||
return close();
|
||||
|
@ -256,7 +253,7 @@ abstract class ResponseContext<RawResponse>
|
|||
return;
|
||||
}
|
||||
|
||||
throw new ArgumentError.notNull('Route to redirect to ($name)');
|
||||
throw ArgumentError.notNull('Route to redirect to ($name)');
|
||||
}
|
||||
|
||||
/// Redirects to the given [Controller] action.
|
||||
|
@ -266,19 +263,19 @@ abstract class ResponseContext<RawResponse>
|
|||
List<String> split = action.split("@");
|
||||
|
||||
if (split.length < 2)
|
||||
throw new Exception(
|
||||
throw Exception(
|
||||
"Controller redirects must take the form of 'Controller@action'. You gave: $action");
|
||||
|
||||
Controller controller =
|
||||
app.controllers[split[0].replaceAll(_straySlashes, '')];
|
||||
|
||||
if (controller == null)
|
||||
throw new Exception("Could not find a controller named '${split[0]}'");
|
||||
throw Exception("Could not find a controller named '${split[0]}'");
|
||||
|
||||
Route matched = controller.routeMappings[split[1]];
|
||||
|
||||
if (matched == null)
|
||||
throw new Exception(
|
||||
throw Exception(
|
||||
"Controller '${split[0]}' does not contain any action named '${split[1]}'");
|
||||
|
||||
final head = controller
|
||||
|
@ -298,7 +295,7 @@ abstract class ResponseContext<RawResponse>
|
|||
/// Serializes data to the response.
|
||||
Future<bool> serialize(value, {MediaType contentType}) async {
|
||||
if (!isOpen) throw closed();
|
||||
this.contentType = contentType ?? new MediaType('application', 'json');
|
||||
this.contentType = contentType ?? MediaType('application', 'json');
|
||||
var text = await serializer(value);
|
||||
if (text.isEmpty) return true;
|
||||
write(text);
|
||||
|
@ -314,7 +311,7 @@ abstract class ResponseContext<RawResponse>
|
|||
var mimeType = app.mimeTypeResolver.lookup(file.path);
|
||||
contentLength = await file.length();
|
||||
contentType = mimeType == null
|
||||
? new MediaType('application', 'octet-stream')
|
||||
? MediaType('application', 'octet-stream')
|
||||
: MediaType.parse(mimeType);
|
||||
|
||||
if (correspondingRequest.method != 'HEAD')
|
||||
|
@ -375,18 +372,18 @@ abstract class ResponseContext<RawResponse>
|
|||
|
||||
abstract class LockableBytesBuilder extends BytesBuilder {
|
||||
factory LockableBytesBuilder() {
|
||||
return new _LockableBytesBuilderImpl();
|
||||
return _LockableBytesBuilderImpl();
|
||||
}
|
||||
|
||||
void lock();
|
||||
}
|
||||
|
||||
class _LockableBytesBuilderImpl implements LockableBytesBuilder {
|
||||
final BytesBuilder _buf = new BytesBuilder(copy: false);
|
||||
final BytesBuilder _buf = BytesBuilder(copy: false);
|
||||
bool _closed = false;
|
||||
|
||||
StateError _deny() =>
|
||||
new StateError('Cannot modified a closed response\'s buffer.');
|
||||
StateError('Cannot modified a closed response\'s buffer.');
|
||||
|
||||
@override
|
||||
void lock() {
|
||||
|
|
|
@ -12,7 +12,7 @@ import 'request_context.dart';
|
|||
import 'response_context.dart';
|
||||
import 'service.dart';
|
||||
|
||||
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
/// A function that receives an incoming [RequestContext] and responds to it.
|
||||
typedef FutureOr RequestHandler(RequestContext req, ResponseContext res);
|
||||
|
@ -31,12 +31,12 @@ RequestHandler chain(Iterable<RequestHandler> handlers) {
|
|||
else {
|
||||
var current = runPipeline;
|
||||
runPipeline = () => current().then((result) => !res.isOpen
|
||||
? new Future.value(result)
|
||||
? Future.value(result)
|
||||
: req.app.executeHandler(handler, req, res));
|
||||
}
|
||||
}
|
||||
|
||||
runPipeline ??= () => new Future.value();
|
||||
runPipeline ??= () => Future.value();
|
||||
return runPipeline();
|
||||
};
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class Routable extends Router<RequestHandler> {
|
|||
final Container _container;
|
||||
|
||||
Routable([Reflector reflector])
|
||||
: _container = reflector == null ? null : new Container(reflector),
|
||||
: _container = reflector == null ? null : Container(reflector),
|
||||
super();
|
||||
|
||||
/// A [Container] used to inject dependencies.
|
||||
|
@ -65,8 +65,7 @@ class Routable extends Router<RequestHandler> {
|
|||
/// A set of [Service] objects that have been mapped into routes.
|
||||
Map<Pattern, Service> get services => _services;
|
||||
|
||||
StreamController<Service> _onService =
|
||||
new StreamController<Service>.broadcast();
|
||||
StreamController<Service> _onService = StreamController<Service>.broadcast();
|
||||
|
||||
/// Fired whenever a service is added to this instance.
|
||||
///
|
||||
|
@ -119,11 +118,9 @@ class Routable extends Router<RequestHandler> {
|
|||
/// events dispatched by this service.
|
||||
HookedService<Id, Data, T> use<Id, Data, T extends Service<Id, Data>>(
|
||||
String path, T service) {
|
||||
var hooked = new HookedService<Id, Data, T>(service);
|
||||
_services[path
|
||||
.toString()
|
||||
.trim()
|
||||
.replaceAll(new RegExp(r'(^/+)|(/+$)'), '')] = hooked;
|
||||
var hooked = HookedService<Id, Data, T>(service);
|
||||
_services[path.toString().trim().replaceAll(RegExp(r'(^/+)|(/+$)'), '')] =
|
||||
hooked;
|
||||
hooked.addRoutes();
|
||||
mount(path.toString(), hooked);
|
||||
service.onHooked(hooked);
|
||||
|
|
|
@ -19,7 +19,7 @@ import 'response_context.dart';
|
|||
import 'routable.dart';
|
||||
import 'service.dart';
|
||||
|
||||
//final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
//final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
/// A function that configures an [Angel] server in some way.
|
||||
typedef FutureOr<void> AngelConfigurer(Angel app);
|
||||
|
@ -37,7 +37,7 @@ class Angel extends Routable {
|
|||
final Map<
|
||||
String,
|
||||
Tuple4<List, Map<String, dynamic>, ParseResult<RouteResult>,
|
||||
MiddlewarePipeline>> handlerCache = new HashMap();
|
||||
MiddlewarePipeline>> handlerCache = HashMap();
|
||||
|
||||
Router<RequestHandler> _flattened;
|
||||
Angel _parent;
|
||||
|
@ -48,7 +48,7 @@ class Angel extends Routable {
|
|||
final Map<dynamic, InjectionRequest> _preContained = {};
|
||||
|
||||
/// A [MimeTypeResolver] that can be used to specify the MIME types of files not known by `package:mime`.
|
||||
final MimeTypeResolver mimeTypeResolver = new MimeTypeResolver();
|
||||
final MimeTypeResolver mimeTypeResolver = MimeTypeResolver();
|
||||
|
||||
/// A middleware to inject a serialize on every request.
|
||||
FutureOr<String> Function(dynamic) serializer;
|
||||
|
@ -65,7 +65,7 @@ class Angel extends Routable {
|
|||
bool allowMethodOverrides = true;
|
||||
|
||||
/// All child application mounted on this instance.
|
||||
List<Angel> get children => new List<Angel>.unmodifiable(_children);
|
||||
List<Angel> get children => List<Angel>.unmodifiable(_children);
|
||||
|
||||
final Map<Pattern, Controller> _controllers = {};
|
||||
|
||||
|
@ -134,7 +134,7 @@ class Angel extends Routable {
|
|||
return;
|
||||
}
|
||||
|
||||
res.contentType = new MediaType('text', 'html', {'charset': 'utf8'});
|
||||
res.contentType = MediaType('text', 'html', {'charset': 'utf8'});
|
||||
res.statusCode = e.statusCode;
|
||||
res.write("<!DOCTYPE html><html><head><title>${e.message}</title>");
|
||||
res.write("</head><body><h1>${e.message}</h1><ul>");
|
||||
|
@ -211,7 +211,7 @@ class Angel extends Routable {
|
|||
shutdownHooks.clear();
|
||||
responseFinalizers.clear();
|
||||
_flattened = null;
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -262,7 +262,7 @@ class Angel extends Routable {
|
|||
return getHandlerResult(handler.toList(), req, res);
|
||||
}
|
||||
|
||||
return new Future.value(handler);
|
||||
return Future.value(handler);
|
||||
}
|
||||
|
||||
/// Runs some [handler]. Returns `true` if request execution should continue.
|
||||
|
@ -305,7 +305,7 @@ class Angel extends Routable {
|
|||
/// the execution will be faster, as the injection requirements were stored beforehand.
|
||||
Future runContained(Function handler, RequestContext req, ResponseContext res,
|
||||
[Container container]) {
|
||||
return new Future.sync(() {
|
||||
return Future.sync(() {
|
||||
if (_preContained.containsKey(handler)) {
|
||||
return handleContained(handler, _preContained[handler], container)(
|
||||
req, res);
|
||||
|
@ -323,13 +323,13 @@ class Angel extends Routable {
|
|||
handler,
|
||||
_preContained[handler] = preInject(handler, container.reflector),
|
||||
container);
|
||||
return new Future.sync(() => h(req, res));
|
||||
return Future.sync(() => h(req, res));
|
||||
// return closureMirror.apply(args).reflectee;
|
||||
}
|
||||
|
||||
/// Applies an [AngelConfigurer] to this instance.
|
||||
Future configure(AngelConfigurer configurer) {
|
||||
return new Future.sync(() => configurer(this));
|
||||
return Future.sync(() => configurer(this));
|
||||
}
|
||||
|
||||
/// Shorthand for using the [container] to instantiate, and then mount a [Controller].
|
||||
|
|
|
@ -107,10 +107,10 @@ class Service<Id, Data> extends Routable {
|
|||
String errorMessage = 'No record was found matching the given query.']) {
|
||||
return index(params).then((result) {
|
||||
if (result == null) {
|
||||
throw new AngelHttpException.notFound(message: errorMessage);
|
||||
throw AngelHttpException.notFound(message: errorMessage);
|
||||
} else {
|
||||
if (result.isEmpty) {
|
||||
throw new AngelHttpException.notFound(message: errorMessage);
|
||||
throw AngelHttpException.notFound(message: errorMessage);
|
||||
} else {
|
||||
return result.first;
|
||||
}
|
||||
|
@ -120,12 +120,12 @@ class Service<Id, Data> extends Routable {
|
|||
|
||||
/// Retrieves all resources.
|
||||
Future<List<Data>> index([Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Retrieves the desired resource.
|
||||
Future<Data> read(Id id, [Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Reads multiple resources at once.
|
||||
|
@ -138,22 +138,22 @@ class Service<Id, Data> extends Routable {
|
|||
|
||||
/// Creates a resource.
|
||||
Future<Data> create(Data data, [Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Modifies a resource.
|
||||
Future<Data> modify(Id id, Data data, [Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Overwrites a resource.
|
||||
Future<Data> update(Id id, Data data, [Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Removes the given resource.
|
||||
Future<Data> remove(Id id, [Map<String, dynamic> params]) {
|
||||
throw new AngelHttpException.methodNotAllowed();
|
||||
throw AngelHttpException.methodNotAllowed();
|
||||
}
|
||||
|
||||
/// Creates an [AnonymousService] that wraps over this one, and maps input and output
|
||||
|
@ -167,7 +167,7 @@ class Service<Id, Data> extends Routable {
|
|||
return encoder(inner);
|
||||
};
|
||||
|
||||
return new AnonymousService<Id, U>(
|
||||
return AnonymousService<Id, U>(
|
||||
readData: readData,
|
||||
index: ([params]) {
|
||||
return index(params).then((it) => it.map(encoder).toList());
|
||||
|
@ -219,7 +219,7 @@ class Service<Id, Data> extends Routable {
|
|||
|
||||
void _addRoutesInner(Service service, Iterable<RequestHandler> handlerss) {
|
||||
var restProvider = {'provider': Providers.rest};
|
||||
var handlers = new List<RequestHandler>.from(handlerss);
|
||||
var handlers = List<RequestHandler>.from(handlerss);
|
||||
|
||||
// Add global middleware if declared on the instance itself
|
||||
Middleware before =
|
||||
|
@ -363,8 +363,8 @@ class Service<Id, Data> extends Routable {
|
|||
(removeMiddleware == null) ? [] : removeMiddleware.handlers));
|
||||
|
||||
// REST compliance
|
||||
put('/', (req, res) => throw new AngelHttpException.notFound());
|
||||
patch('/', (req, res) => throw new AngelHttpException.notFound());
|
||||
put('/', (req, res) => throw AngelHttpException.notFound());
|
||||
patch('/', (req, res) => throw AngelHttpException.notFound());
|
||||
}
|
||||
|
||||
/// Invoked when this service is wrapped within a [HookedService].
|
||||
|
|
|
@ -13,33 +13,33 @@ import '../core/core.dart';
|
|||
import 'http_request_context.dart';
|
||||
import 'http_response_context.dart';
|
||||
|
||||
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
/// Adapts `dart:io`'s [HttpServer] to serve Angel.
|
||||
class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
||||
HttpRequestContext, HttpResponseContext> {
|
||||
@override
|
||||
Uri get uri =>
|
||||
new Uri(scheme: 'http', host: server.address.address, port: server.port);
|
||||
Uri(scheme: 'http', host: server.address.address, port: server.port);
|
||||
|
||||
AngelHttp._(Angel app,
|
||||
Future<HttpServer> Function(dynamic, int) serverGenerator, bool useZone)
|
||||
: super(app, serverGenerator, useZone: useZone);
|
||||
|
||||
factory AngelHttp(Angel app, {bool useZone = true}) {
|
||||
return new AngelHttp._(app, HttpServer.bind, useZone);
|
||||
return AngelHttp._(app, HttpServer.bind, useZone);
|
||||
}
|
||||
|
||||
/// An instance mounted on a server started by the [serverGenerator].
|
||||
factory AngelHttp.custom(
|
||||
Angel app, Future<HttpServer> Function(dynamic, int) serverGenerator,
|
||||
{bool useZone = true}) {
|
||||
return new AngelHttp._(app, serverGenerator, useZone);
|
||||
return AngelHttp._(app, serverGenerator, useZone);
|
||||
}
|
||||
|
||||
factory AngelHttp.fromSecurityContext(Angel app, SecurityContext context,
|
||||
{bool useZone = true}) {
|
||||
return new AngelHttp._(app, (address, int port) {
|
||||
return AngelHttp._(app, (address, int port) {
|
||||
return HttpServer.bindSecure(address, port, context);
|
||||
}, useZone);
|
||||
}
|
||||
|
@ -55,11 +55,10 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
var certificateChain =
|
||||
Platform.script.resolve(certificateChainPath).toFilePath();
|
||||
var serverKey = Platform.script.resolve(serverKeyPath).toFilePath();
|
||||
var serverContext = new SecurityContext();
|
||||
var serverContext = SecurityContext();
|
||||
serverContext.useCertificateChain(certificateChain, password: password);
|
||||
serverContext.usePrivateKey(serverKey, password: password);
|
||||
return new AngelHttp.fromSecurityContext(app, serverContext,
|
||||
useZone: useZone);
|
||||
return AngelHttp.fromSecurityContext(app, serverContext, useZone: useZone);
|
||||
}
|
||||
|
||||
/// Use [server] instead.
|
||||
|
@ -94,8 +93,8 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
Future<HttpResponseContext> createResponseContext(
|
||||
HttpRequest request, HttpResponse response,
|
||||
[HttpRequestContext correspondingRequest]) {
|
||||
return new Future<HttpResponseContext>.value(
|
||||
new HttpResponseContext(response, app, correspondingRequest)
|
||||
return Future<HttpResponseContext>.value(
|
||||
HttpResponseContext(response, app, correspondingRequest)
|
||||
..serializer = (app.serializer ?? json.encode)
|
||||
..encoders.addAll(app.encoders ?? {}));
|
||||
}
|
||||
|
@ -103,7 +102,7 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
|
|||
@override
|
||||
Stream<HttpResponse> createResponseStreamFromRawRequest(
|
||||
HttpRequest request) =>
|
||||
new Stream.fromIterable([request.response]);
|
||||
Stream.fromIterable([request.response]);
|
||||
|
||||
@override
|
||||
void setChunkedEncoding(HttpResponse response, bool value) =>
|
||||
|
|
|
@ -75,7 +75,7 @@ class HttpRequestContext extends RequestContext<HttpRequest> {
|
|||
/// Magically transforms an [HttpRequest] into a [RequestContext].
|
||||
static Future<HttpRequestContext> from(
|
||||
HttpRequest request, Angel app, String path) {
|
||||
HttpRequestContext ctx = new HttpRequestContext()
|
||||
HttpRequestContext ctx = HttpRequestContext()
|
||||
.._container = app.container.createChild();
|
||||
|
||||
String override = request.method;
|
||||
|
@ -114,15 +114,15 @@ class HttpRequestContext extends RequestContext<HttpRequest> {
|
|||
}
|
||||
|
||||
if (lastSlash > -1)
|
||||
ctx._path = new String.fromCharCodes(_path.take(lastSlash));
|
||||
ctx._path = String.fromCharCodes(_path.take(lastSlash));
|
||||
else
|
||||
ctx._path = new String.fromCharCodes(_path);
|
||||
ctx._path = String.fromCharCodes(_path);
|
||||
*/
|
||||
|
||||
ctx._path = path;
|
||||
ctx._io = request;
|
||||
|
||||
return new Future.value(ctx);
|
||||
return Future.value(ctx);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -51,7 +51,7 @@ class HttpResponseContext extends ResponseContext<HttpResponse> {
|
|||
|
||||
@override
|
||||
void useBuffer() {
|
||||
_buffer = new LockableBytesBuilder();
|
||||
_buffer = LockableBytesBuilder();
|
||||
}
|
||||
|
||||
Iterable<String> __allowedEncodings;
|
||||
|
@ -92,7 +92,7 @@ class HttpResponseContext extends ResponseContext<HttpResponse> {
|
|||
rawResponse.contentLength;
|
||||
}
|
||||
|
||||
rawResponse.headers.contentType = new ContentType(
|
||||
rawResponse.headers.contentType = ContentType(
|
||||
contentType.type, contentType.subtype,
|
||||
charset: contentType.parameters['charset'],
|
||||
parameters: contentType.parameters);
|
||||
|
@ -209,6 +209,6 @@ class HttpResponseContext extends ResponseContext<HttpResponse> {
|
|||
|
||||
super.close();
|
||||
}
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@ Future<SecureServerSocket> startSharedHttp2(
|
|||
class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
||||
SecureServerSocket, Http2RequestContext, Http2ResponseContext> {
|
||||
final ServerSettings settings;
|
||||
final StreamController<HttpRequest> _onHttp1 = new StreamController();
|
||||
final StreamController<HttpRequest> _onHttp1 = StreamController();
|
||||
final Map<String, MockHttpSession> _sessions = {};
|
||||
final Uuid _uuid = new Uuid();
|
||||
final Uuid _uuid = Uuid();
|
||||
_AngelHttp2ServerSocket _artificial;
|
||||
|
||||
SecureServerSocket get socket => _artificial;
|
||||
|
@ -39,7 +39,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
|
||||
factory AngelHttp2(Angel app, SecurityContext securityContext,
|
||||
{bool useZone = true, ServerSettings settings}) {
|
||||
return new AngelHttp2.custom(app, securityContext, SecureServerSocket.bind,
|
||||
return AngelHttp2.custom(app, securityContext, SecureServerSocket.bind,
|
||||
settings: settings);
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,10 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
address, int port, SecurityContext ctx),
|
||||
{bool useZone = true,
|
||||
ServerSettings settings}) {
|
||||
return new AngelHttp2._(app, (address, port) {
|
||||
return AngelHttp2._(app, (address, port) {
|
||||
var addr = address is InternetAddress
|
||||
? address
|
||||
: new InternetAddress(address.toString());
|
||||
: InternetAddress(address.toString());
|
||||
return Future.sync(() => serverGenerator(addr, port, ctx));
|
||||
}, useZone, settings);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
@override
|
||||
Future<SecureServerSocket> generateServer([address, int port]) async {
|
||||
var s = await serverGenerator(address ?? '127.0.0.1', port ?? 0);
|
||||
return _artificial = new _AngelHttp2ServerSocket(s, this);
|
||||
return _artificial = _AngelHttp2ServerSocket(s, this);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -75,15 +75,15 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
|
||||
@override
|
||||
void addCookies(ServerTransportStream response, Iterable<Cookie> cookies) {
|
||||
var headers = cookies
|
||||
.map((cookie) => new Header.ascii('set-cookie', cookie.toString()));
|
||||
var headers =
|
||||
cookies.map((cookie) => Header.ascii('set-cookie', cookie.toString()));
|
||||
response.sendHeaders(headers.toList());
|
||||
}
|
||||
|
||||
@override
|
||||
Future closeResponse(ServerTransportStream response) {
|
||||
response.terminate();
|
||||
return new Future.value();
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -96,7 +96,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
Future<Http2ResponseContext> createResponseContext(
|
||||
Socket request, ServerTransportStream response,
|
||||
[Http2RequestContext correspondingRequest]) async {
|
||||
return new Http2ResponseContext(app, response, correspondingRequest)
|
||||
return Http2ResponseContext(app, response, correspondingRequest)
|
||||
..encoders.addAll(app.encoders);
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
Stream<ServerTransportStream> createResponseStreamFromRawRequest(
|
||||
Socket request) {
|
||||
var connection =
|
||||
new ServerTransportConnection.viaSocket(request, settings: settings);
|
||||
ServerTransportConnection.viaSocket(request, settings: settings);
|
||||
return connection.incomingStreams;
|
||||
}
|
||||
|
||||
|
@ -120,12 +120,12 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
|
||||
@override
|
||||
void setHeader(ServerTransportStream response, String key, String value) {
|
||||
response.sendHeaders([new Header.ascii(key, value)]);
|
||||
response.sendHeaders([Header.ascii(key, value)]);
|
||||
}
|
||||
|
||||
@override
|
||||
void setStatusCode(ServerTransportStream response, int value) {
|
||||
response.sendHeaders([new Header.ascii(':status', value.toString())]);
|
||||
response.sendHeaders([Header.ascii(':status', value.toString())]);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -147,7 +147,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
|
|||
|
||||
class _FakeServerSocket extends Stream<Socket> implements ServerSocket {
|
||||
final _AngelHttp2ServerSocket angel;
|
||||
final _ctrl = new StreamController<Socket>();
|
||||
final _ctrl = StreamController<Socket>();
|
||||
|
||||
_FakeServerSocket(this.angel);
|
||||
|
||||
|
@ -175,13 +175,13 @@ class _AngelHttp2ServerSocket extends Stream<SecureSocket>
|
|||
implements SecureServerSocket {
|
||||
final SecureServerSocket socket;
|
||||
final AngelHttp2 driver;
|
||||
final _ctrl = new StreamController<SecureSocket>();
|
||||
final _ctrl = StreamController<SecureSocket>();
|
||||
_FakeServerSocket _fake;
|
||||
StreamSubscription _sub;
|
||||
|
||||
_AngelHttp2ServerSocket(this.socket, this.driver) {
|
||||
_fake = new _FakeServerSocket(this);
|
||||
new HttpServer.listenOn(_fake).pipe(driver._onHttp1);
|
||||
_fake = _FakeServerSocket(this);
|
||||
HttpServer.listenOn(_fake).pipe(driver._onHttp1);
|
||||
_sub = socket.listen(
|
||||
(socket) {
|
||||
if (socket.selectedProtocol == null ||
|
||||
|
@ -193,7 +193,7 @@ class _AngelHttp2ServerSocket extends Stream<SecureSocket>
|
|||
_ctrl.add(socket);
|
||||
} else {
|
||||
socket.destroy();
|
||||
throw new Exception(
|
||||
throw Exception(
|
||||
'AngelHttp2 does not support ${socket.selectedProtocol} as an ALPN protocol.');
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,11 +7,11 @@ import 'package:http2/transport.dart';
|
|||
import 'package:mock_request/mock_request.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
final RegExp _comma = new RegExp(r',\s*');
|
||||
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
final RegExp _comma = RegExp(r',\s*');
|
||||
final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
class Http2RequestContext extends RequestContext<ServerTransportStream> {
|
||||
final StreamController<List<int>> _body = new StreamController();
|
||||
final StreamController<List<int>> _body = StreamController();
|
||||
final Container container;
|
||||
List<Cookie> _cookies;
|
||||
HttpHeaders _headers;
|
||||
|
@ -32,13 +32,13 @@ class Http2RequestContext extends RequestContext<ServerTransportStream> {
|
|||
Angel app,
|
||||
Map<String, MockHttpSession> sessions,
|
||||
Uuid uuid) {
|
||||
var c = new Completer<Http2RequestContext>();
|
||||
var req = new Http2RequestContext._(app.container.createChild())
|
||||
var c = Completer<Http2RequestContext>();
|
||||
var req = Http2RequestContext._(app.container.createChild())
|
||||
..app = app
|
||||
.._socket = socket
|
||||
.._stream = stream;
|
||||
|
||||
var headers = req._headers = new MockHttpHeaders();
|
||||
var headers = req._headers = MockHttpHeaders();
|
||||
// String scheme = 'https', host = socket.address.address, path = '';
|
||||
var uri =
|
||||
Uri(scheme: 'https', host: socket.address.address, port: socket.port);
|
||||
|
@ -46,7 +46,7 @@ class Http2RequestContext extends RequestContext<ServerTransportStream> {
|
|||
|
||||
void finalize() {
|
||||
req
|
||||
.._cookies = new List.unmodifiable(cookies)
|
||||
.._cookies = List.unmodifiable(cookies)
|
||||
.._uri = uri;
|
||||
if (!c.isCompleted) c.complete(req);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ class Http2RequestContext extends RequestContext<ServerTransportStream> {
|
|||
|
||||
for (var cookieString in cookieStrings) {
|
||||
try {
|
||||
cookies.add(new Cookie.fromSetCookieValue(cookieString));
|
||||
cookies.add(Cookie.fromSetCookieValue(cookieString));
|
||||
} catch (_) {
|
||||
// Ignore malformed cookies, and just don't add them to the container.
|
||||
}
|
||||
|
@ -127,12 +127,12 @@ class Http2RequestContext extends RequestContext<ServerTransportStream> {
|
|||
cookies.firstWhere((c) => c.name == 'DARTSESSID', orElse: () => null);
|
||||
|
||||
if (dartSessId == null) {
|
||||
dartSessId = new Cookie('DARTSESSID', uuid.v4());
|
||||
dartSessId = Cookie('DARTSESSID', uuid.v4());
|
||||
}
|
||||
|
||||
req._session = sessions.putIfAbsent(
|
||||
dartSessId.value,
|
||||
() => new MockHttpSession(id: dartSessId.value),
|
||||
() => MockHttpSession(id: dartSessId.value),
|
||||
);
|
||||
|
||||
return c.future;
|
||||
|
|
|
@ -34,7 +34,7 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
bool get canPush => stream.canPush;
|
||||
|
||||
/// Returns a [List] of all resources that have [push]ed to the client.
|
||||
List<Http2ResponseContext> get pushes => new List.unmodifiable(_pushes);
|
||||
List<Http2ResponseContext> get pushes => List.unmodifiable(_pushes);
|
||||
|
||||
@override
|
||||
ServerTransportStream detach() {
|
||||
|
@ -65,7 +65,7 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
|
||||
@override
|
||||
void useBuffer() {
|
||||
_buffer = new LockableBytesBuilder();
|
||||
_buffer = LockableBytesBuilder();
|
||||
}
|
||||
|
||||
/// Write headers, status, etc. to the underlying [stream].
|
||||
|
@ -73,7 +73,7 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
if (_isPush || _streamInitialized) return false;
|
||||
|
||||
var headers = <Header>[
|
||||
new Header.ascii(':status', statusCode.toString()),
|
||||
Header.ascii(':status', statusCode.toString()),
|
||||
];
|
||||
|
||||
if (encoders.isNotEmpty && correspondingRequest != null) {
|
||||
|
@ -98,15 +98,15 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
|
||||
// Add all normal headers
|
||||
for (var key in this.headers.keys) {
|
||||
headers.add(new Header.ascii(key.toLowerCase(), this.headers[key]));
|
||||
headers.add(Header.ascii(key.toLowerCase(), this.headers[key]));
|
||||
}
|
||||
|
||||
// Persist session ID
|
||||
cookies.add(new Cookie('DARTSESSID', _req.session.id));
|
||||
cookies.add(Cookie('DARTSESSID', _req.session.id));
|
||||
|
||||
// Send all cookies
|
||||
for (var cookie in cookies) {
|
||||
headers.add(new Header.ascii('set-cookie', cookie.toString()));
|
||||
headers.add(Header.ascii('set-cookie', cookie.toString()));
|
||||
}
|
||||
|
||||
stream.sendHeaders(headers);
|
||||
|
@ -210,18 +210,18 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
|
|||
var targetUri = _req.uri.replace(path: path);
|
||||
|
||||
var h = <Header>[
|
||||
new Header.ascii(':authority', targetUri.authority),
|
||||
new Header.ascii(':method', method),
|
||||
new Header.ascii(':path', targetUri.path),
|
||||
new Header.ascii(':scheme', targetUri.scheme),
|
||||
Header.ascii(':authority', targetUri.authority),
|
||||
Header.ascii(':method', method),
|
||||
Header.ascii(':path', targetUri.path),
|
||||
Header.ascii(':scheme', targetUri.scheme),
|
||||
];
|
||||
|
||||
for (var key in headers.keys) {
|
||||
h.add(new Header.ascii(key, headers[key]));
|
||||
h.add(Header.ascii(key, headers[key]));
|
||||
}
|
||||
|
||||
var s = stream.push(h);
|
||||
var r = new Http2ResponseContext(app, s, _req)
|
||||
var r = Http2ResponseContext(app, s, _req)
|
||||
.._isPush = true
|
||||
.._targetUri = targetUri;
|
||||
_pushes.add(r);
|
||||
|
|
|
@ -4,9 +4,9 @@ typedef void _InitCallback();
|
|||
|
||||
/// A [StreamController] boilerplate that prevents memory leaks.
|
||||
abstract class SafeCtrl<T> {
|
||||
factory SafeCtrl() => new _SingleSafeCtrl();
|
||||
factory SafeCtrl() => _SingleSafeCtrl();
|
||||
|
||||
factory SafeCtrl.broadcast() => new _BroadcastSafeCtrl();
|
||||
factory SafeCtrl.broadcast() => _BroadcastSafeCtrl();
|
||||
|
||||
Stream<T> get stream;
|
||||
|
||||
|
@ -25,7 +25,7 @@ class _SingleSafeCtrl<T> implements SafeCtrl<T> {
|
|||
_InitCallback _initializer;
|
||||
|
||||
_SingleSafeCtrl() {
|
||||
_stream = new StreamController<T>(onListen: () {
|
||||
_stream = StreamController<T>(onListen: () {
|
||||
_hasListener = true;
|
||||
|
||||
if (!_initialized && _initializer != null) {
|
||||
|
@ -79,7 +79,7 @@ class _BroadcastSafeCtrl<T> implements SafeCtrl<T> {
|
|||
_InitCallback _initializer;
|
||||
|
||||
_BroadcastSafeCtrl() {
|
||||
_stream = new StreamController<T>.broadcast(onListen: () {
|
||||
_stream = StreamController<T>.broadcast(onListen: () {
|
||||
_listeners++;
|
||||
|
||||
if (!_initialized && _initializer != null) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:angel_container/angel_container.dart';
|
||||
|
||||
final RegExp straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||
final RegExp straySlashes = RegExp(r'(^/+)|(/+$)');
|
||||
|
||||
T matchingAnnotation<T>(List<ReflectedInstance> metadata) {
|
||||
for (ReflectedInstance metaDatum in metadata) {
|
||||
|
|
|
@ -5,8 +5,8 @@ import 'package:angel_framework/angel_framework.dart';
|
|||
import 'package:angel_framework/http.dart';
|
||||
|
||||
main() async {
|
||||
var app = new Angel();
|
||||
var http = new AngelHttp.custom(app, startShared, useZone: false);
|
||||
var app = Angel();
|
||||
var http = AngelHttp.custom(app, startShared, useZone: false);
|
||||
|
||||
app.get('/', (req, res) => res.write('Hello, world!'));
|
||||
app.optimizeForProduction(force: true);
|
||||
|
|
|
@ -59,10 +59,10 @@ main() {
|
|||
Future<RequestContext> acceptContentTypes(
|
||||
[Iterable<String> contentTypes = const []]) {
|
||||
var headerString = contentTypes.isEmpty ? null : contentTypes.join(',');
|
||||
var rq = new MockHttpRequest('GET', ENDPOINT);
|
||||
var rq = MockHttpRequest('GET', ENDPOINT);
|
||||
rq.headers.set('accept', headerString);
|
||||
rq.close();
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp(app);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var http = AngelHttp(app);
|
||||
return http.createRequestContext(rq, rq.response);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:test/test.dart';
|
|||
|
||||
main() {
|
||||
test('custom methods', () async {
|
||||
var svc = new AnonymousService<String, String>(
|
||||
var svc = AnonymousService<String, String>(
|
||||
index: ([p]) async => ['index'],
|
||||
read: (id, [p]) async => 'read',
|
||||
create: (data, [p]) async => 'create',
|
||||
|
@ -20,21 +20,21 @@ main() {
|
|||
|
||||
test('defaults to throwing', () async {
|
||||
try {
|
||||
var svc = new AnonymousService();
|
||||
var svc = AnonymousService();
|
||||
await svc.read(1);
|
||||
throw 'Should have thrown 405!';
|
||||
} on AngelHttpException {
|
||||
// print('Ok!');
|
||||
}
|
||||
try {
|
||||
var svc = new AnonymousService();
|
||||
var svc = AnonymousService();
|
||||
await svc.modify(2, null);
|
||||
throw 'Should have thrown 405!';
|
||||
} on AngelHttpException {
|
||||
// print('Ok!');
|
||||
}
|
||||
try {
|
||||
var svc = new AnonymousService();
|
||||
var svc = AnonymousService();
|
||||
await svc.update(3, null);
|
||||
throw 'Should have thrown 405!';
|
||||
} on AngelHttpException {
|
||||
|
|
|
@ -32,12 +32,12 @@ incrementTodoTimes(e) {
|
|||
IncrementService.TIMES++;
|
||||
}
|
||||
|
||||
@Hooks(before: const [incrementTodoTimes])
|
||||
@Hooks(before: [incrementTodoTimes])
|
||||
class IncrementService extends Service {
|
||||
static int TIMES = 0;
|
||||
|
||||
@override
|
||||
@Hooks(after: const [incrementTodoTimes])
|
||||
@Hooks(after: [incrementTodoTimes])
|
||||
index([params]) async => [];
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import 'common.dart';
|
|||
|
||||
@Expose("/todos", middleware: [foo])
|
||||
class TodoController extends Controller {
|
||||
List<Todo> todos = [new Todo(text: "Hello", over: "world")];
|
||||
List<Todo> todos = [Todo(text: "Hello", over: "world")];
|
||||
|
||||
@Expose("/:id", middleware: [bar])
|
||||
Future<Todo> fetchTodo(
|
||||
|
@ -34,7 +34,7 @@ class NoExposeController extends Controller {}
|
|||
|
||||
@Expose('/named', as: 'foo')
|
||||
class NamedController extends Controller {
|
||||
@Expose('/optional/:arg?', allowNull: const ['arg'])
|
||||
@Expose('/optional/:arg?', allowNull: ['arg'])
|
||||
optional() => 2;
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,11 @@ main() {
|
|||
Angel app;
|
||||
TodoController ctrl;
|
||||
HttpServer server;
|
||||
http.Client client = new http.Client();
|
||||
http.Client client = http.Client();
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
app.get(
|
||||
"/redirect",
|
||||
(req, res) async =>
|
||||
|
@ -64,7 +64,7 @@ main() {
|
|||
|
||||
// Register as a singleton, just for the purpose of this test
|
||||
if (!app.container.has<TodoController>())
|
||||
app.container.registerSingleton(ctrl = new TodoController());
|
||||
app.container.registerSingleton(ctrl = TodoController());
|
||||
|
||||
// Using mountController<T>();
|
||||
await app.mountController<TodoController>();
|
||||
|
@ -72,7 +72,7 @@ main() {
|
|||
print(app.controllers);
|
||||
app.dumpTree();
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
server = await AngelHttp(app).startServer();
|
||||
url = 'http://${server.address.address}:${server.port}';
|
||||
});
|
||||
|
||||
|
@ -88,8 +88,8 @@ main() {
|
|||
|
||||
test('require expose', () async {
|
||||
try {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
await app.configure(new NoExposeController().configureServer);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
await app.configure(NoExposeController().configureServer);
|
||||
throw 'Should require @Expose';
|
||||
} on Exception {
|
||||
// :)
|
||||
|
@ -97,26 +97,26 @@ main() {
|
|||
});
|
||||
|
||||
test('create dynamic handler', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
app.get(
|
||||
'/foo',
|
||||
ioc(({String bar}) {
|
||||
return 2;
|
||||
}, optional: ['bar']));
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: 'foo'));
|
||||
await new AngelHttp(app).handleRequest(rq);
|
||||
var rq = MockHttpRequest('GET', Uri(path: 'foo'));
|
||||
await AngelHttp(app).handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
expect(json.decode(body), 2);
|
||||
});
|
||||
|
||||
test('optional name', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
await app.configure(new NamedController().configureServer);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
await app.configure(NamedController().configureServer);
|
||||
expect(app.controllers['foo'], const IsInstanceOf<NamedController>());
|
||||
});
|
||||
|
||||
test("middleware", () async {
|
||||
var rgx = new RegExp("^Hello, world!");
|
||||
var rgx = RegExp("^Hello, world!");
|
||||
var response = await client.get("$url/todos/0");
|
||||
print('Response: ${response.body}');
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ void main() {
|
|||
AngelHttp http;
|
||||
|
||||
setUp(() async {
|
||||
var app = new Angel();
|
||||
http = new AngelHttp(app);
|
||||
var app = Angel();
|
||||
http = AngelHttp(app);
|
||||
|
||||
app.get('/detach', (req, res) async {
|
||||
if (res is HttpResponseContext) {
|
||||
|
@ -17,7 +17,7 @@ void main() {
|
|||
io..write('Hey!');
|
||||
await io.close();
|
||||
} else {
|
||||
throw new StateError('This endpoint only supports HTTP/1.1.');
|
||||
throw StateError('This endpoint only supports HTTP/1.1.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ void main() {
|
|||
tearDown(() => http.close());
|
||||
|
||||
test('detach response', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/detach'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/detach'));
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
await http.handleRequest(rq);
|
||||
|
|
|
@ -21,11 +21,11 @@ main() {
|
|||
String url;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
client = new http.Client();
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
client = http.Client();
|
||||
|
||||
// Inject some todos
|
||||
app.container.registerSingleton(new Todo(text: TEXT, over: OVER));
|
||||
app.container.registerSingleton(Todo(text: TEXT, over: OVER));
|
||||
app.container.registerFactory<Future<Foo>>((container) async {
|
||||
var req = container.make<RequestContext>();
|
||||
var text = await req.body.transform(utf8.decoder).join();
|
||||
|
@ -38,10 +38,10 @@ main() {
|
|||
ioc(({Errand singleton, Todo foo, RequestContext req}) =>
|
||||
singleton.text));
|
||||
app.post('/async', ioc((Foo foo) => {'baz': foo.bar}));
|
||||
await app.configure(new SingletonController().configureServer);
|
||||
await app.configure(new ErrandController().configureServer);
|
||||
await app.configure(SingletonController().configureServer);
|
||||
await app.configure(ErrandController().configureServer);
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
server = await AngelHttp(app).startServer();
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
@ -54,18 +54,18 @@ main() {
|
|||
});
|
||||
|
||||
test('runContained with custom container', () async {
|
||||
var app = new Angel();
|
||||
var c = new Container(const MirrorsReflector());
|
||||
c.registerSingleton(new Todo(text: 'Hey!'));
|
||||
var app = Angel();
|
||||
var c = Container(const MirrorsReflector());
|
||||
c.registerSingleton(Todo(text: 'Hey!'));
|
||||
|
||||
app.get('/', (req, res) async {
|
||||
return app.runContained((Todo t) => t.text, req, res, c);
|
||||
});
|
||||
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: '/'));
|
||||
var rq = MockHttpRequest('GET', Uri(path: '/'));
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
await new AngelHttp(app).handleRequest(rq);
|
||||
await AngelHttp(app).handleRequest(rq);
|
||||
var text = await rs.transform(utf8.decoder).join();
|
||||
expect(text, json.encode('Hey!'));
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ import 'package:test/test.dart';
|
|||
|
||||
Future<List<int>> getBody(MockHttpResponse rs) async {
|
||||
var list = await rs.toList();
|
||||
var bb = new BytesBuilder();
|
||||
var bb = BytesBuilder();
|
||||
list.forEach(bb.add);
|
||||
return bb.takeBytes();
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ main() {
|
|||
Angel app;
|
||||
|
||||
setUp(() {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
app.encoders.addAll(
|
||||
{
|
||||
'deflate': zlib.encoder,
|
||||
|
@ -47,11 +47,11 @@ void encodingTests(Angel getApp()) {
|
|||
|
||||
setUp(() {
|
||||
app = getApp();
|
||||
http = new AngelHttp(app);
|
||||
http = AngelHttp(app);
|
||||
});
|
||||
|
||||
test('sends plaintext if no accept-encoding', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/hello'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/hello'));
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
await http.handleRequest(rq);
|
||||
|
@ -61,7 +61,7 @@ void encodingTests(Angel getApp()) {
|
|||
});
|
||||
|
||||
test('encodes if wildcard', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
..headers.set('accept-encoding', '*');
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
|
@ -74,7 +74,7 @@ void encodingTests(Angel getApp()) {
|
|||
});
|
||||
|
||||
test('encodes if wildcard + multiple', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
..headers.set('accept-encoding', ['foo', 'bar', '*']);
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
|
@ -86,7 +86,7 @@ void encodingTests(Angel getApp()) {
|
|||
});
|
||||
|
||||
test('encodes if explicit', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
..headers.set('accept-encoding', 'gzip');
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
|
@ -98,7 +98,7 @@ void encodingTests(Angel getApp()) {
|
|||
});
|
||||
|
||||
test('only uses one encoder', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/hello'))
|
||||
..headers.set('accept-encoding', ['gzip', 'deflate']);
|
||||
await rq.close();
|
||||
var rs = rq.response;
|
||||
|
|
|
@ -5,54 +5,51 @@ import 'package:test/test.dart';
|
|||
|
||||
main() {
|
||||
test('named constructors', () {
|
||||
expect(new AngelHttpException.badRequest(),
|
||||
isException(400, '400 Bad Request'));
|
||||
expect(new AngelHttpException.notAuthenticated(),
|
||||
expect(
|
||||
AngelHttpException.badRequest(), isException(400, '400 Bad Request'));
|
||||
expect(AngelHttpException.notAuthenticated(),
|
||||
isException(401, '401 Not Authenticated'));
|
||||
expect(new AngelHttpException.paymentRequired(),
|
||||
expect(AngelHttpException.paymentRequired(),
|
||||
isException(402, '402 Payment Required'));
|
||||
expect(
|
||||
new AngelHttpException.forbidden(), isException(403, '403 Forbidden'));
|
||||
expect(
|
||||
new AngelHttpException.notFound(), isException(404, '404 Not Found'));
|
||||
expect(new AngelHttpException.methodNotAllowed(),
|
||||
expect(AngelHttpException.forbidden(), isException(403, '403 Forbidden'));
|
||||
expect(AngelHttpException.notFound(), isException(404, '404 Not Found'));
|
||||
expect(AngelHttpException.methodNotAllowed(),
|
||||
isException(405, '405 Method Not Allowed'));
|
||||
expect(new AngelHttpException.notAcceptable(),
|
||||
expect(AngelHttpException.notAcceptable(),
|
||||
isException(406, '406 Not Acceptable'));
|
||||
expect(new AngelHttpException.methodTimeout(),
|
||||
isException(408, '408 Timeout'));
|
||||
expect(new AngelHttpException.conflict(), isException(409, '409 Conflict'));
|
||||
expect(new AngelHttpException.notProcessable(),
|
||||
expect(AngelHttpException.methodTimeout(), isException(408, '408 Timeout'));
|
||||
expect(AngelHttpException.conflict(), isException(409, '409 Conflict'));
|
||||
expect(AngelHttpException.notProcessable(),
|
||||
isException(422, '422 Not Processable'));
|
||||
expect(new AngelHttpException.notImplemented(),
|
||||
expect(AngelHttpException.notImplemented(),
|
||||
isException(501, '501 Not Implemented'));
|
||||
expect(new AngelHttpException.unavailable(),
|
||||
isException(503, '503 Unavailable'));
|
||||
expect(
|
||||
AngelHttpException.unavailable(), isException(503, '503 Unavailable'));
|
||||
});
|
||||
|
||||
test('fromMap', () {
|
||||
expect(new AngelHttpException.fromMap({'status_code': -1, 'message': 'ok'}),
|
||||
expect(AngelHttpException.fromMap({'status_code': -1, 'message': 'ok'}),
|
||||
isException(-1, 'ok'));
|
||||
});
|
||||
|
||||
test('toMap = toJson', () {
|
||||
var exc = new AngelHttpException.badRequest();
|
||||
var exc = AngelHttpException.badRequest();
|
||||
expect(exc.toMap(), exc.toJson());
|
||||
var json_ = json.encode(exc.toJson());
|
||||
var exc2 = new AngelHttpException.fromJson(json_);
|
||||
var exc2 = AngelHttpException.fromJson(json_);
|
||||
expect(exc2.toJson(), exc.toJson());
|
||||
});
|
||||
|
||||
test('toString', () {
|
||||
expect(
|
||||
new AngelHttpException(null, statusCode: 420, message: 'Blaze It')
|
||||
AngelHttpException(null, statusCode: 420, message: 'Blaze It')
|
||||
.toString(),
|
||||
'420: Blaze It');
|
||||
});
|
||||
}
|
||||
|
||||
Matcher isException(int statusCode, String message) =>
|
||||
new _IsException(statusCode, message);
|
||||
_IsException(statusCode, message);
|
||||
|
||||
class _IsException extends Matcher {
|
||||
final int statusCode;
|
||||
|
|
|
@ -25,8 +25,8 @@ main() {
|
|||
}
|
||||
|
||||
Future<RequestContext> makeRequest(String path) {
|
||||
var rq = new MockHttpRequest('GET', ENDPOINT.replace(path: path))..close();
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp(app);
|
||||
var rq = MockHttpRequest('GET', ENDPOINT.replace(path: path))..close();
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var http = AngelHttp(app);
|
||||
return http.createRequestContext(rq, rq.response);
|
||||
}
|
||||
|
|
|
@ -7,17 +7,17 @@ void main() {
|
|||
throwsA(const IsInstanceOf<AngelHttpException>());
|
||||
|
||||
test('throw 404 on null', () {
|
||||
var service = new AnonymousService(index: ([p]) => null);
|
||||
var service = AnonymousService(index: ([p]) => null);
|
||||
expect(() => service.findOne(), throwsAnAngelHttpException);
|
||||
});
|
||||
|
||||
test('throw 404 on empty iterable', () {
|
||||
var service = new AnonymousService(index: ([p]) => []);
|
||||
var service = AnonymousService(index: ([p]) => []);
|
||||
expect(() => service.findOne(), throwsAnAngelHttpException);
|
||||
});
|
||||
|
||||
test('return first element of iterable', () async {
|
||||
var service = new AnonymousService(index: ([p]) => [2]);
|
||||
var service = AnonymousService(index: ([p]) => [2]);
|
||||
expect(await service.findOne(), 2);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ main() {
|
|||
String url;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
app = Angel(reflector: MirrorsReflector())
|
||||
..post('/foo', (req, res) => res.serialize({'hello': 'world'}))
|
||||
..all('*', (req, res) => throw new AngelHttpException.notFound());
|
||||
client = new http.Client();
|
||||
..all('*', (req, res) => throw AngelHttpException.notFound());
|
||||
client = http.Client();
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
server = await AngelHttp(app).startServer();
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'all.dart' as hm;
|
|||
|
||||
main() async {
|
||||
var zone = Zone.current.fork(
|
||||
specification: new ZoneSpecification(print: (self, parent, zone, line) {
|
||||
specification: ZoneSpecification(print: (self, parent, zone, line) {
|
||||
if (line == 'null') {
|
||||
parent.print(zone, cyan.wrap(StackTrace.current.toString()));
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ main() {
|
|||
HookedService todoService;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
client = new http.Client();
|
||||
app.use('/todos', new MapService());
|
||||
app.use('/books', new BookService());
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
client = http.Client();
|
||||
app.use('/todos', MapService());
|
||||
app.use('/books', BookService());
|
||||
|
||||
todoService = app.findHookedService<MapService>('todos');
|
||||
|
||||
|
@ -35,7 +35,7 @@ main() {
|
|||
throw e.error;
|
||||
};
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
server = await AngelHttp(app).startServer();
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
@ -106,7 +106,7 @@ main() {
|
|||
});
|
||||
|
||||
test('metadata', () async {
|
||||
final service = new HookedService(new IncrementService())..addHooks(app);
|
||||
final service = HookedService(IncrementService())..addHooks(app);
|
||||
expect(service.inner, isNot(const IsInstanceOf<MapService>()));
|
||||
IncrementService.TIMES = 0;
|
||||
await service.index();
|
||||
|
@ -131,7 +131,7 @@ main() {
|
|||
});
|
||||
|
||||
test('contains provider in before and after', () async {
|
||||
var svc = new HookedService(new AnonymousService(index: ([p]) async => []));
|
||||
var svc = HookedService(AnonymousService(index: ([p]) async => []));
|
||||
|
||||
ensureProviderIsPresent(HookedServiceEvent e) {
|
||||
var type = e.isBefore ? 'before' : 'after';
|
||||
|
|
|
@ -17,18 +17,17 @@ const String jfk =
|
|||
'Ask not what your country can do for you, but what you can do for your country.';
|
||||
|
||||
Stream<List<int>> jfkStream() {
|
||||
return new Stream.fromIterable([utf8.encode(jfk)]);
|
||||
return Stream.fromIterable([utf8.encode(jfk)]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
var client = new Http2Client();
|
||||
var client = Http2Client();
|
||||
Angel app;
|
||||
AngelHttp2 http2;
|
||||
Uri serverRoot;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
..encoders['gzip'] = gzip.encoder;
|
||||
app = Angel(reflector: MirrorsReflector())..encoders['gzip'] = gzip.encoder;
|
||||
hierarchicalLoggingEnabled = true;
|
||||
app.logger = Logger.detached('angel.http2')
|
||||
..onRecord.listen((rec) {
|
||||
|
@ -93,12 +92,12 @@ void main() {
|
|||
return req.queryParameters;
|
||||
});
|
||||
|
||||
var ctx = new SecurityContext()
|
||||
var ctx = SecurityContext()
|
||||
..useCertificateChain('dev.pem')
|
||||
..usePrivateKey('dev.key', password: 'dartdart')
|
||||
..setAlpnProtocols(['h2'], true);
|
||||
|
||||
http2 = new AngelHttp2(app, ctx);
|
||||
http2 = AngelHttp2(app, ctx);
|
||||
|
||||
var server = await http2.startServer();
|
||||
serverRoot = Uri.parse('https://127.0.0.1:${server.port}');
|
||||
|
@ -181,16 +180,16 @@ void main() {
|
|||
supportedProtocols: ['h2'],
|
||||
);
|
||||
|
||||
var connection = new ClientTransportConnection.viaSocket(
|
||||
var connection = ClientTransportConnection.viaSocket(
|
||||
socket,
|
||||
settings: new ClientSettings(allowServerPushes: true),
|
||||
settings: ClientSettings(allowServerPushes: true),
|
||||
);
|
||||
|
||||
var headers = <Header>[
|
||||
new Header.ascii(':authority', serverRoot.authority),
|
||||
new Header.ascii(':method', 'GET'),
|
||||
new Header.ascii(':path', serverRoot.replace(path: '/push').path),
|
||||
new Header.ascii(':scheme', serverRoot.scheme),
|
||||
Header.ascii(':authority', serverRoot.authority),
|
||||
Header.ascii(':method', 'GET'),
|
||||
Header.ascii(':path', serverRoot.replace(path: '/push').path),
|
||||
Header.ascii(':scheme', serverRoot.scheme),
|
||||
];
|
||||
|
||||
var stream = await connection.makeRequest(headers, endStream: true);
|
||||
|
@ -198,8 +197,7 @@ void main() {
|
|||
var bb = await stream.incomingMessages
|
||||
.where((s) => s is DataStreamMessage)
|
||||
.cast<DataStreamMessage>()
|
||||
.fold<BytesBuilder>(
|
||||
new BytesBuilder(), (out, msg) => out..add(msg.bytes));
|
||||
.fold<BytesBuilder>(BytesBuilder(), (out, msg) => out..add(msg.bytes));
|
||||
|
||||
// Check that main body was sent
|
||||
expect(utf8.decode(bb.takeBytes()), 'ok');
|
||||
|
@ -231,7 +229,7 @@ void main() {
|
|||
.where((s) => s is DataStreamMessage)
|
||||
.cast<DataStreamMessage>()
|
||||
.fold<BytesBuilder>(
|
||||
new BytesBuilder(), (out, msg) => out..add(msg.bytes));
|
||||
BytesBuilder(), (out, msg) => out..add(msg.bytes));
|
||||
return UTF8.decode(bb.takeBytes());
|
||||
}
|
||||
*/
|
||||
|
@ -268,14 +266,14 @@ void main() {
|
|||
});
|
||||
|
||||
test('multipart body parsed', () async {
|
||||
var rq = new http.MultipartRequest(
|
||||
'POST', serverRoot.replace(path: '/upload'));
|
||||
var rq =
|
||||
http.MultipartRequest('POST', serverRoot.replace(path: '/upload'));
|
||||
rq.headers.addAll({'accept': 'application/json'});
|
||||
|
||||
rq.fields['foo'] = 'bar';
|
||||
rq.files.add(new http.MultipartFile(
|
||||
'file', new Stream.fromIterable([utf8.encode('hello world')]), 11,
|
||||
contentType: new MediaType('angel', 'framework')));
|
||||
rq.files.add(http.MultipartFile(
|
||||
'file', Stream.fromIterable([utf8.encode('hello world')]), 11,
|
||||
contentType: MediaType('angel', 'framework')));
|
||||
|
||||
var response = await client.send(rq);
|
||||
var responseBody = await response.stream.transform(utf8.decoder).join();
|
||||
|
|
|
@ -17,29 +17,29 @@ class Http2Client extends BaseClient {
|
|||
supportedProtocols: ['h2'],
|
||||
);
|
||||
|
||||
var connection = new ClientTransportConnection.viaSocket(socket);
|
||||
var connection = ClientTransportConnection.viaSocket(socket);
|
||||
|
||||
var headers = <Header>[
|
||||
new Header.ascii(':authority', request.url.authority),
|
||||
new Header.ascii(':method', request.method),
|
||||
new Header.ascii(
|
||||
Header.ascii(':authority', request.url.authority),
|
||||
Header.ascii(':method', request.method),
|
||||
Header.ascii(
|
||||
':path',
|
||||
request.url.path +
|
||||
(request.url.hasQuery ? ('?' + request.url.query) : '')),
|
||||
new Header.ascii(':scheme', request.url.scheme),
|
||||
Header.ascii(':scheme', request.url.scheme),
|
||||
];
|
||||
|
||||
var bb = await request
|
||||
.finalize()
|
||||
.fold<BytesBuilder>(new BytesBuilder(), (out, list) => out..add(list));
|
||||
.fold<BytesBuilder>(BytesBuilder(), (out, list) => out..add(list));
|
||||
var body = bb.takeBytes();
|
||||
|
||||
if (body.isNotEmpty) {
|
||||
headers.add(new Header.ascii('content-length', body.length.toString()));
|
||||
headers.add(Header.ascii('content-length', body.length.toString()));
|
||||
}
|
||||
|
||||
request.headers.forEach((k, v) {
|
||||
headers.add(new Header.ascii(k, v));
|
||||
headers.add(Header.ascii(k, v));
|
||||
});
|
||||
|
||||
var stream = await connection.makeRequest(headers, endStream: body.isEmpty);
|
||||
|
@ -56,7 +56,7 @@ class Http2Client extends BaseClient {
|
|||
/// Returns `true` if the response stream was closed.
|
||||
static Future<bool> readResponse(ClientTransportStream stream,
|
||||
Map<String, String> headers, BytesBuilder body) {
|
||||
var c = new Completer<bool>();
|
||||
var c = Completer<bool>();
|
||||
var closed = false;
|
||||
|
||||
stream.incomingMessages.listen(
|
||||
|
@ -86,10 +86,10 @@ class Http2Client extends BaseClient {
|
|||
Future<StreamedResponse> send(BaseRequest request) async {
|
||||
var stream = await convertRequestToStream(request);
|
||||
var headers = <String, String>{};
|
||||
var body = new BytesBuilder();
|
||||
var body = BytesBuilder();
|
||||
var closed = await readResponse(stream, headers, body);
|
||||
return new StreamedResponse(
|
||||
new Stream.fromIterable([body.takeBytes()]),
|
||||
return StreamedResponse(
|
||||
Stream.fromIterable([body.takeBytes()]),
|
||||
int.parse(headers[':status']),
|
||||
headers: headers,
|
||||
isRedirect: headers.containsKey('location'),
|
||||
|
|
|
@ -27,8 +27,8 @@ parameterMetaTests() {
|
|||
AngelHttp http;
|
||||
|
||||
setUp(() {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
http = new AngelHttp(app);
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
http = AngelHttp(app);
|
||||
|
||||
app.get('/cookie', ioc((@CookieValue('token') String jwt) {
|
||||
return jwt;
|
||||
|
@ -58,7 +58,7 @@ parameterMetaTests() {
|
|||
return 'DEFAULT $mode';
|
||||
}));
|
||||
|
||||
/*app.logger = new Logger('parameter_meta_test')
|
||||
/*app.logger = Logger('parameter_meta_test')
|
||||
..onRecord.listen((rec) {
|
||||
print(rec);
|
||||
if (rec.error != null) print(rec.error);
|
||||
|
@ -69,7 +69,7 @@ parameterMetaTests() {
|
|||
|
||||
test('injects header or throws', () async {
|
||||
// Invalid request
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/header'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/header'));
|
||||
unawaited(rq.close());
|
||||
var rs = rq.response;
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
@ -78,7 +78,7 @@ parameterMetaTests() {
|
|||
expect(rs.statusCode, 400);
|
||||
|
||||
// Valid request
|
||||
rq = new MockHttpRequest('GET', Uri.parse('/header'))
|
||||
rq = MockHttpRequest('GET', Uri.parse('/header'))
|
||||
..headers.add('x-foo', 'bar');
|
||||
unawaited(rq.close());
|
||||
rs = rq.response;
|
||||
|
@ -92,7 +92,7 @@ parameterMetaTests() {
|
|||
|
||||
test('injects session or throws', () async {
|
||||
// Invalid request
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/session'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/session'));
|
||||
unawaited(rq.close());
|
||||
var rs = rq.response;
|
||||
unawaited(http
|
||||
|
@ -103,7 +103,7 @@ parameterMetaTests() {
|
|||
await printResponse(rs);
|
||||
expect(rs.statusCode, 500);
|
||||
|
||||
rq = new MockHttpRequest('GET', Uri.parse('/session'));
|
||||
rq = MockHttpRequest('GET', Uri.parse('/session'));
|
||||
rq.session['foo'] = 'bar';
|
||||
unawaited(rq.close());
|
||||
rs = rq.response;
|
||||
|
@ -118,7 +118,7 @@ parameterMetaTests() {
|
|||
// they will all function the same way.
|
||||
|
||||
test('pattern matching', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/match?mode=pos'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/match?mode=pos'));
|
||||
unawaited(rq.close());
|
||||
var rs = rq.response;
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
@ -127,7 +127,7 @@ parameterMetaTests() {
|
|||
expect(rs.statusCode, 200);
|
||||
expect(body, json.encode('YES pos'));
|
||||
|
||||
rq = new MockHttpRequest('GET', Uri.parse('/match?mode=neg'));
|
||||
rq = MockHttpRequest('GET', Uri.parse('/match?mode=neg'));
|
||||
unawaited(rq.close());
|
||||
rs = rq.response;
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
@ -137,7 +137,7 @@ parameterMetaTests() {
|
|||
expect(body, json.encode('NO neg'));
|
||||
|
||||
// Fallback
|
||||
rq = new MockHttpRequest('GET', Uri.parse('/match?mode=ambi'));
|
||||
rq = MockHttpRequest('GET', Uri.parse('/match?mode=ambi'));
|
||||
unawaited(rq.close());
|
||||
rs = rq.response;
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
|
|
@ -9,16 +9,16 @@ import 'package:test/test.dart';
|
|||
|
||||
main() {
|
||||
test('preinjects functions', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector())
|
||||
var app = Angel(reflector: MirrorsReflector())
|
||||
..configuration['foo'] = 'bar'
|
||||
..get('/foo', ioc(echoAppFoo));
|
||||
app.optimizeForProduction(force: true);
|
||||
print(app.preContained);
|
||||
expect(app.preContained.keys, contains(echoAppFoo));
|
||||
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: '/foo'));
|
||||
var rq = MockHttpRequest('GET', Uri(path: '/foo'));
|
||||
unawaited(rq.close());
|
||||
await new AngelHttp(app).handleRequest(rq);
|
||||
await AngelHttp(app).handleRequest(rq);
|
||||
var rs = rq.response;
|
||||
var body = await rs.transform(utf8.decoder).join();
|
||||
expect(body, json.encode('bar'));
|
||||
|
|
|
@ -13,9 +13,9 @@ main() {
|
|||
AngelHttp http;
|
||||
|
||||
setUp(() {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
app = Angel(reflector: MirrorsReflector())
|
||||
..configuration['global'] = 305; // Pitbull!
|
||||
http = new AngelHttp(app);
|
||||
http = AngelHttp(app);
|
||||
|
||||
app.get('/string/:string', ioc((String string) => string));
|
||||
|
||||
|
@ -39,7 +39,7 @@ main() {
|
|||
tearDown(() => app.close());
|
||||
|
||||
test('String type annotation', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/string/hello'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/string/hello'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var rs = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -47,7 +47,7 @@ main() {
|
|||
});
|
||||
|
||||
test('Primitive after parsed param injection', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/num/parsed/24'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/num/parsed/24'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var rs = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -55,7 +55,7 @@ main() {
|
|||
});
|
||||
|
||||
test('globally-injected primitive', () async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/num/global'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/num/global'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var rs = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -64,12 +64,12 @@ main() {
|
|||
|
||||
test('unparsed primitive throws error', () async {
|
||||
try {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/num/unparsed/32'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/num/unparsed/32'));
|
||||
unawaited(rq.close());
|
||||
var req = await http.createRequestContext(rq, rq.response);
|
||||
var res = await http.createResponseContext(rq, rq.response, req);
|
||||
await app.runContained((num unparsed) => unparsed, req, res);
|
||||
throw new StateError(
|
||||
throw StateError(
|
||||
'ArgumentError should be thrown if a parameter cannot be resolved.');
|
||||
} on ArgumentError {
|
||||
// Success
|
||||
|
|
|
@ -9,14 +9,14 @@ import 'package:test/test.dart';
|
|||
|
||||
main() {
|
||||
MockHttpRequest mk(int id) {
|
||||
return new MockHttpRequest('GET', Uri.parse('/test/$id'))..close();
|
||||
return MockHttpRequest('GET', Uri.parse('/test/$id'))..close();
|
||||
}
|
||||
|
||||
test('can request the same url twice', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector())
|
||||
var app = Angel(reflector: MirrorsReflector())
|
||||
..get('/test/:id', ioc((id) => 'Hello $id'));
|
||||
var rq1 = mk(1), rq2 = mk(2), rq3 = mk(1);
|
||||
await Future.wait([rq1, rq2, rq3].map(new AngelHttp(app).handleRequest));
|
||||
await Future.wait([rq1, rq2, rq3].map(AngelHttp(app).handleRequest));
|
||||
var body1 = await rq1.response.transform(utf8.decoder).join(),
|
||||
body2 = await rq2.response.transform(utf8.decoder).join(),
|
||||
body3 = await rq3.response.transform(utf8.decoder).join();
|
||||
|
|
|
@ -42,12 +42,12 @@ main() {
|
|||
http.Client client;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
nested = new Angel(reflector: MirrorsReflector());
|
||||
todos = new Angel(reflector: MirrorsReflector());
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
nested = Angel(reflector: MirrorsReflector());
|
||||
todos = Angel(reflector: MirrorsReflector());
|
||||
|
||||
[app, nested, todos].forEach((Angel app) {
|
||||
app.logger = new Logger('routing_test')
|
||||
app.logger = Logger('routing_test')
|
||||
..onRecord.listen((rec) {
|
||||
if (rec.error != null) {
|
||||
stdout
|
||||
|
@ -95,7 +95,7 @@ main() {
|
|||
app.get('/method', (req, res) => 'Only GET');
|
||||
app.post('/method', (req, res) => 'Only POST');
|
||||
|
||||
app.use('/query', new QueryService());
|
||||
app.use('/query', QueryService());
|
||||
|
||||
RequestHandler write(String message) {
|
||||
return (req, res) {
|
||||
|
@ -111,8 +111,8 @@ main() {
|
|||
|
||||
//app.dumpTree(header: "DUMPING ROUTES:", showMatchers: true);
|
||||
|
||||
client = new http.Client();
|
||||
var server = await new AngelHttp(app).startServer('127.0.0.1', 0);
|
||||
client = http.Client();
|
||||
var server = await AngelHttp(app).startServer('127.0.0.1', 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
|
|
@ -14,15 +14,15 @@ main() {
|
|||
String url;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
app = Angel(reflector: MirrorsReflector())
|
||||
..get('/foo', ioc(() => {'hello': 'world'}))
|
||||
..get('/bar', (req, res) async {
|
||||
await res.serialize({'hello': 'world'},
|
||||
contentType: new MediaType('text', 'html'));
|
||||
contentType: MediaType('text', 'html'));
|
||||
});
|
||||
client = new http.Client();
|
||||
client = http.Client();
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
server = await AngelHttp(app).startServer();
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
|
|
@ -15,9 +15,8 @@ final Uri $foo = Uri.parse('http://localhost:3000/foo');
|
|||
/// Additional tests to improve coverage of server.dart
|
||||
main() {
|
||||
group('scoping', () {
|
||||
var parent = new Angel(reflector: MirrorsReflector())
|
||||
..configuration['two'] = 2;
|
||||
var child = new Angel(reflector: MirrorsReflector());
|
||||
var parent = Angel(reflector: MirrorsReflector())..configuration['two'] = 2;
|
||||
var child = Angel(reflector: MirrorsReflector());
|
||||
parent.mount('/child', child);
|
||||
|
||||
test('sets children', () {
|
||||
|
@ -34,20 +33,20 @@ main() {
|
|||
});
|
||||
|
||||
test('custom server generator', () {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp.custom(app, HttpServer.bind);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var http = AngelHttp.custom(app, HttpServer.bind);
|
||||
expect(http.serverGenerator, HttpServer.bind);
|
||||
});
|
||||
|
||||
test('default error handler', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp(app);
|
||||
var rq = new MockHttpRequest('GET', $foo);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var http = AngelHttp(app);
|
||||
var rq = MockHttpRequest('GET', $foo);
|
||||
unawaited(rq.close());
|
||||
var rs = rq.response;
|
||||
var req = await http.createRequestContext(rq, rs);
|
||||
var res = await http.createResponseContext(rq, rs);
|
||||
var e = new AngelHttpException(null,
|
||||
var e = AngelHttpException(null,
|
||||
statusCode: 321, message: 'Hello', errors: ['foo', 'bar']);
|
||||
await app.errorHandler(e, req, res);
|
||||
await http.sendResponse(rq, rs, req, res);
|
||||
|
@ -63,10 +62,10 @@ main() {
|
|||
});
|
||||
|
||||
test('plug-ins run on startup', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
app.startupHooks.add((app) => app.configuration['two'] = 2);
|
||||
|
||||
var http = new AngelHttp(app);
|
||||
var http = AngelHttp(app);
|
||||
await http.startServer();
|
||||
expect(app.configuration['two'], 2);
|
||||
await app.close();
|
||||
|
@ -74,16 +73,16 @@ main() {
|
|||
});
|
||||
|
||||
test('warning when adding routes to flattened router', () {
|
||||
var app = new Angel(reflector: MirrorsReflector())
|
||||
var app = Angel(reflector: MirrorsReflector())
|
||||
..optimizeForProduction(force: true);
|
||||
app.dumpTree();
|
||||
app.get('/', (req, res) => 2);
|
||||
app.mount('/foo', new Router()..get('/', (req, res) => 3));
|
||||
app.mount('/foo', Router()..get('/', (req, res) => 3));
|
||||
});
|
||||
|
||||
test('services close on close call', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var svc = new CustomCloseService();
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var svc = CustomCloseService();
|
||||
expect(svc.value, 2);
|
||||
app.use('/', svc);
|
||||
await app.close();
|
||||
|
@ -91,11 +90,10 @@ main() {
|
|||
});
|
||||
|
||||
test('global injection added to injection map', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector())
|
||||
..configuration['a'] = 'b';
|
||||
var http = new AngelHttp(app);
|
||||
var app = Angel(reflector: MirrorsReflector())..configuration['a'] = 'b';
|
||||
var http = AngelHttp(app);
|
||||
app.get('/', ioc((String a) => a));
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -103,10 +101,10 @@ main() {
|
|||
});
|
||||
|
||||
test('global injected serializer', () async {
|
||||
var app = new Angel(reflector: MirrorsReflector())..serializer = (_) => 'x';
|
||||
var http = new AngelHttp(app);
|
||||
var app = Angel(reflector: MirrorsReflector())..serializer = (_) => 'x';
|
||||
var http = AngelHttp(app);
|
||||
app.get($foo.path, (req, ResponseContext res) => res.serialize(null));
|
||||
var rq = new MockHttpRequest('GET', $foo);
|
||||
var rq = MockHttpRequest('GET', $foo);
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -114,15 +112,15 @@ main() {
|
|||
});
|
||||
|
||||
group('handler results', () {
|
||||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp(app);
|
||||
var app = Angel(reflector: MirrorsReflector());
|
||||
var http = AngelHttp(app);
|
||||
app.responseFinalizers
|
||||
.add((req, res) => throw new AngelHttpException.forbidden());
|
||||
.add((req, res) => throw AngelHttpException.forbidden());
|
||||
RequestContext req;
|
||||
ResponseContext res;
|
||||
|
||||
setUp(() async {
|
||||
var rq = new MockHttpRequest('GET', $foo);
|
||||
var rq = MockHttpRequest('GET', $foo);
|
||||
unawaited(rq.close());
|
||||
req = await http.createRequestContext(rq, rq.response);
|
||||
res = await http.createResponseContext(rq, rq.response);
|
||||
|
@ -138,14 +136,14 @@ main() {
|
|||
});
|
||||
|
||||
test('return future', () async {
|
||||
var handler = new Future.value(2);
|
||||
var handler = Future.value(2);
|
||||
expect(await app.getHandlerResult(handler, req, res), 2);
|
||||
});
|
||||
});
|
||||
|
||||
group('executeHandler', () {
|
||||
test('return Stream', () async {
|
||||
var handler = (req, res) => new Stream.fromIterable([2, 3]);
|
||||
var handler = (req, res) => Stream.fromIterable([2, 3]);
|
||||
expect(await app.executeHandler(handler, req, res), isFalse);
|
||||
});
|
||||
|
||||
|
@ -161,10 +159,10 @@ main() {
|
|||
AngelHttp http;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
app.get('/wtf', (req, res) => throw new AngelHttpException.forbidden());
|
||||
app.get('/wtf2', (req, res) => throw new AngelHttpException.forbidden());
|
||||
http = new AngelHttp(app);
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
app.get('/wtf', (req, res) => throw AngelHttpException.forbidden());
|
||||
app.get('/wtf2', (req, res) => throw AngelHttpException.forbidden());
|
||||
http = AngelHttp(app);
|
||||
await http.startServer('127.0.0.1', 0);
|
||||
|
||||
var oldHandler = app.errorHandler;
|
||||
|
@ -178,7 +176,7 @@ main() {
|
|||
tearDown(() => app.close());
|
||||
|
||||
test('can send json', () async {
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: 'wtf'))
|
||||
var rq = MockHttpRequest('GET', Uri(path: 'wtf'))
|
||||
..headers.set('accept', 'application/json');
|
||||
unawaited(rq.close());
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
@ -188,7 +186,7 @@ main() {
|
|||
});
|
||||
|
||||
test('can throw in finalizer', () async {
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: 'wtf'))
|
||||
var rq = MockHttpRequest('GET', Uri(path: 'wtf'))
|
||||
..headers.set('accept', 'application/json');
|
||||
unawaited(rq.close());
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
@ -198,7 +196,7 @@ main() {
|
|||
});
|
||||
|
||||
test('can send html', () async {
|
||||
var rq = new MockHttpRequest('GET', new Uri(path: 'wtf2'));
|
||||
var rq = MockHttpRequest('GET', Uri(path: 'wtf2'));
|
||||
rq.headers.set('accept', 'text/html');
|
||||
unawaited(rq.close());
|
||||
unawaited(http.handleRequest(rq));
|
||||
|
|
|
@ -6,18 +6,18 @@ void main() {
|
|||
Service<String, Todo> mapped;
|
||||
|
||||
setUp(() {
|
||||
inner = new MapService();
|
||||
inner = MapService();
|
||||
mapped = inner.map<Todo>(Todo.fromMap, Todo.toMap);
|
||||
});
|
||||
|
||||
test('create', () async {
|
||||
var result = await mapped.create(
|
||||
new Todo(text: 'hello', complete: false),
|
||||
Todo(text: 'hello', complete: false),
|
||||
);
|
||||
print(result);
|
||||
expect(
|
||||
result,
|
||||
new Todo(text: 'hello', complete: false),
|
||||
Todo(text: 'hello', complete: false),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -26,7 +26,7 @@ void main() {
|
|||
String id;
|
||||
|
||||
setUp(() async {
|
||||
result = await mapped.create(new Todo(text: 'hello', complete: false));
|
||||
result = await mapped.create(Todo(text: 'hello', complete: false));
|
||||
id = result.id;
|
||||
});
|
||||
|
||||
|
@ -35,12 +35,12 @@ void main() {
|
|||
});
|
||||
|
||||
test('modify', () async {
|
||||
var newTodo = new Todo(text: 'yes', complete: true);
|
||||
var newTodo = Todo(text: 'yes', complete: true);
|
||||
expect(await mapped.update(id, newTodo), newTodo);
|
||||
});
|
||||
|
||||
test('update', () async {
|
||||
var newTodo = new Todo(id: 'hmmm', text: 'yes', complete: true);
|
||||
var newTodo = Todo(id: 'hmmm', text: 'yes', complete: true);
|
||||
expect(await mapped.update(id, newTodo), newTodo);
|
||||
});
|
||||
|
||||
|
@ -61,7 +61,7 @@ class Todo {
|
|||
Todo({this.id, this.text, this.complete});
|
||||
|
||||
static Todo fromMap(Map<String, dynamic> json) {
|
||||
return new Todo(
|
||||
return Todo(
|
||||
id: json['id'] as String,
|
||||
text: json['text'] as String,
|
||||
complete: json['complete'] as bool);
|
||||
|
|
|
@ -22,15 +22,15 @@ main() {
|
|||
http.Client client;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
..use('/todos', service = new MapService())
|
||||
app = Angel(reflector: MirrorsReflector())
|
||||
..use('/todos', service = MapService())
|
||||
..errorHandler = (e, req, res) {
|
||||
if (e.error != null) print('Whoops: ${e.error}');
|
||||
if (e.stackTrace != null) print(new Chain.forTrace(e.stackTrace).terse);
|
||||
if (e.stackTrace != null) print(Chain.forTrace(e.stackTrace).terse);
|
||||
};
|
||||
|
||||
var server = await new AngelHttp(app).startServer();
|
||||
client = new http.Client();
|
||||
var server = await AngelHttp(app).startServer();
|
||||
client = http.Client();
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ main() {
|
|||
AngelHttp http;
|
||||
|
||||
setUp(() {
|
||||
app = new Angel(reflector: MirrorsReflector());
|
||||
http = new AngelHttp(app, useZone: true);
|
||||
app = Angel(reflector: MirrorsReflector());
|
||||
http = AngelHttp(app, useZone: true);
|
||||
|
||||
app.logger = new Logger('streaming_test')
|
||||
app.logger = Logger('streaming_test')
|
||||
..onRecord.listen((rec) {
|
||||
print(rec);
|
||||
if (rec.stackTrace != null) print(rec.stackTrace);
|
||||
|
@ -35,31 +35,30 @@ main() {
|
|||
);
|
||||
|
||||
app.get('/hello', (req, res) {
|
||||
return new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
return Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
.pipe(res);
|
||||
});
|
||||
|
||||
app.get('/write', (req, res) async {
|
||||
await res.addStream(
|
||||
new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
res.write('bye');
|
||||
await res.close();
|
||||
});
|
||||
|
||||
app.get('/multiple', (req, res) async {
|
||||
await res.addStream(
|
||||
new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
await res
|
||||
.addStream(new Stream<List<int>>.fromIterable(['bye'.codeUnits]));
|
||||
Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
await res.addStream(Stream<List<int>>.fromIterable(['bye'.codeUnits]));
|
||||
await res.close();
|
||||
});
|
||||
|
||||
app.get('/overwrite', (req, res) async {
|
||||
res.statusCode = 32;
|
||||
await new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
await Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
.pipe(res);
|
||||
|
||||
var f = new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
var f = Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
.pipe(res)
|
||||
.then((_) => false)
|
||||
.catchError((_) => true);
|
||||
|
@ -67,7 +66,7 @@ main() {
|
|||
expect(f, completion(true));
|
||||
});
|
||||
|
||||
app.get('/error', (req, res) => res.addError(new StateError('wtf')));
|
||||
app.get('/error', (req, res) => res.addError(StateError('wtf')));
|
||||
|
||||
app.errorHandler = (e, req, res) async {
|
||||
stderr..writeln(e.error)..writeln(e.stackTrace);
|
||||
|
@ -77,7 +76,7 @@ main() {
|
|||
tearDown(() => http.close());
|
||||
|
||||
_expectHelloBye(String path) async {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse(path));
|
||||
var rq = MockHttpRequest('GET', Uri.parse(path));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -90,7 +89,7 @@ main() {
|
|||
|
||||
test('cannot write after close', () async {
|
||||
try {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/overwrite'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/overwrite'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
|
@ -104,7 +103,7 @@ main() {
|
|||
|
||||
test('res => addError', () async {
|
||||
try {
|
||||
var rq = new MockHttpRequest('GET', Uri.parse('/error'));
|
||||
var rq = MockHttpRequest('GET', Uri.parse('/error'));
|
||||
unawaited(rq.close());
|
||||
await http.handleRequest(rq);
|
||||
var body = await rq.response.transform(utf8.decoder).join();
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:test/test.dart';
|
|||
|
||||
main() {
|
||||
test('default view generator', () async {
|
||||
var app = new Angel();
|
||||
var app = Angel();
|
||||
var view = await app.viewGenerator('foo', {'bar': 'baz'});
|
||||
expect(view, contains('No view engine'));
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue